Problem: You have a directed acyclic graph G, consisting of n vertexes, numbered from 0 to n - 1. The graph contains n edges numbered from 0 to n - 1. An edge with number i connects vertexes i and (i + 1) mod n, and it can be directed in either direction (from i to (i + 1) mod n, or vise versa).

Operation x mod y means taking the remainder after dividing number x by number y.

Let's call two vertexes u and v in graph G comparable if the graph contains a path either from u to v or from v to u. We'll assume that an antichain is a set of vertexes of graph G, where any two distinct vertexes are not comparable. The size of an antichain is the number of vertexes in the corresponding set. An antichain is maximum if the graph doesn't have antichains of a larger size.

Your task is to find the size of the maximum antichain in graph G.

Input

The first line contains the sequence of characters s0s1... sn - 1 (2 ≤ n ≤ 106), consisting of numbers zero and one. The length of the line (number n) corresponds to the number of vertexes and edges in graph G. If character si (i ≥ 0) equals 0, then the edge between vertexes i and (i + 1) mod n is directed from the i-th vertex to the (i + 1) mod n-th one, otherwise — to the opposite point.

It is guaranteed that the given graph is acyclic.

Output

Print a single integer — the size of the maximum antichain of graph G.

Examples

Input

001


Output

1


Input

110010


Output

3

Note

Consider the first test sample. The graph's G edges are: 0 → 1, 1 → 2, 0 → 2. We can choose the set of vertexes [0] as the maximum antichain. We cannot choose an antichain of larger size.

Solution (in JAVA):

Solution:


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class E {
	static char[] edges;
	static int[] nextZero, nextOne;
	static int zeroLimit;
	static int[][] dp;

	// 0 not-taken not reachable, 1 taken, 2 reachable, 3 not reachable
	public static int solve(int idx, int zeroTaken) {
		if (idx < 0)
			return 0;
		if (idx >= edges.length)
			return 0;
		// System.out.println(idx+" "+edges.length);
		if (idx == edges.length - 1) {
			if (zeroTaken == 0) {
				return 1;
			} else if (zeroTaken == 1) {
				return 0;
			} else if (zeroTaken == 2) {
				if (edges[idx] == '0')
					return 1;
				return 0;
			} else {
				if (edges[idx] == '1')
					return 1;
				return 0;
			}
		}
		if (dp[idx][zeroTaken] != -1)
			return dp[idx][zeroTaken];
		int tmp = solve(idx + 1, zeroTaken);
		if (edges[idx] == '0') {
			if (idx <= zeroLimit) {
				if (idx == 0) {
					tmp = Math.max(tmp, 1 + solve(nextOne[idx] + 1, 1));
				} else {
					if (edges[0] == '0') {
						tmp = Math.max(tmp, 1 + solve(nextOne[idx] + 1, 3));
					} else {
						tmp = Math.max(tmp, 1 + solve(nextOne[idx] + 1, 2));
					}
				}
			} else {
				tmp = Math.max(tmp, 1 + solve(nextOne[idx] + 1, zeroTaken));
			}
		} else {
			if (idx <= zeroLimit) {
				if (idx == 0) {
					tmp = Math.max(tmp, 1 + solve(nextZero[idx] + 1, 1));
				} else {
					if (edges[0] == '0') {
						tmp = Math.max(tmp, 1 + solve(nextZero[idx] + 1, 3));
					} else {
						tmp = Math.max(tmp, 1 + solve(nextZero[idx] + 1, 2));
					}
				}
			} else {
				tmp = Math.max(tmp, 1 + solve(nextZero[idx] + 1, zeroTaken));
			}
		}
		return dp[idx][zeroTaken] = tmp;
	}

	public static int fillOne(int i) {
		if (nextOne[i] != 0)
			return nextOne[i];
		if (i == edges.length - 1) {
			return nextOne[i] = edges.length;
		}
		if (edges[i + 1] == '1') {
			return nextOne[i] = i + 1;
		} else {
			return nextOne[i] = fillOne(i + 1);
		}
	}

	public static int fillZero(int i) {
		if (nextZero[i] != 0)
			return nextZero[i];
		if (i == edges.length - 1) {
			return nextZero[i] = edges.length;
		}
		if (edges[i + 1] == '0') {
			return nextZero[i] = i + 1;
		} else {
			return nextZero[i] = fillZero(i + 1);
		}
	}

	public static void main(String[] args) throws Exception {
		edges = next().toCharArray();
		nextOne = new int[edges.length];
		nextZero = new int[edges.length];
		for (int i = 0; i < edges.length; i++) {
			if (nextOne[i] == 0) {
				fillOne(i);
			}
			if (nextZero[i] == 0) {
				fillZero(i);
			}
		}
		for (int i = 1; i < edges.length; i++) {
			if (edges[i] != edges[0]) {
				zeroLimit = i;
				break;
			}
		}
		dp = new int[edges.length + 2][4];
		for (int i = 0; i < dp.length; i++)
			Arrays.fill(dp[i], -1);
//		System.out.println(solve(0, 0));
		for (int idx = edges.length + 1; idx >= 0; idx--) {
			for (int zeroTaken = 0; zeroTaken < 4; zeroTaken++) {
				if (idx >= edges.length) {
					dp[idx][zeroTaken] = 0;
					continue;
				}
				if (idx == edges.length - 1) {
					if (zeroTaken == 0) {
						dp[idx][zeroTaken] = 1;
					} else if (zeroTaken == 1) {
						dp[idx][zeroTaken] = 0;
					} else if (zeroTaken == 2) {
						if (edges[idx] == '0')
							dp[idx][zeroTaken] = 1;
						else
							dp[idx][zeroTaken] = 0;
					} else {
						if (edges[idx] == '1')
							dp[idx][zeroTaken] = 1;
						else
							dp[idx][zeroTaken] = 0;
					}
					continue;
				}
				int tmp = dp[idx + 1][zeroTaken];
				if (edges[idx] == '0') {
					if (idx <= zeroLimit) {
						if (idx == 0) {
							tmp = Math.max(tmp, 1 + dp[nextOne[idx] + 1][1]);
						} else {
							if (edges[0] == '0') {
								tmp = Math
										.max(tmp, 1 + dp[nextOne[idx] + 1][3]);
							} else {
								tmp = Math
										.max(tmp, 1 + dp[nextOne[idx] + 1][2]);
							}
						}
					} else {
						if(nextOne[idx]!=edges.length||(nextOne[idx]==edges.length&&(zeroTaken==0||zeroTaken==2)))
						tmp = Math
								.max(tmp, 1 + dp[nextOne[idx] + 1][zeroTaken]);
					}
				} else {
					if (idx <= zeroLimit) {
						if (idx == 0) {
							tmp = Math.max(tmp, 1 + dp[nextZero[idx] + 1][1]);
						} else {
							if (edges[0] == '0') {
								tmp = Math.max(tmp,
										1 + dp[nextZero[idx] + 1][3]);
							} else {
								tmp = Math.max(tmp,
										1 + dp[nextZero[idx] + 1][2]);
							}
						}
					} else {
						if(nextZero[idx]!=edges.length||(nextZero[idx]==edges.length&&(zeroTaken==0||zeroTaken==3)))
						tmp = Math.max(tmp,
								1 + dp[nextZero[idx] + 1][zeroTaken]);
					}
				}
				dp[idx][zeroTaken] = tmp;
			}
		}
		System.out.println(dp[0][ 0]);
		// System.out.println(Arrays.toString(nextOne));
		// System.out.println(Arrays.toString(nextZero));
	}

	static BufferedReader br = new BufferedReader(new InputStreamReader(
			System.in));
	static StringTokenizer tokenizer = new StringTokenizer("");

	static int nextInt() throws Exception {
		return Integer.parseInt(next());
	}

	static double nextDouble() throws Exception {
		return Double.parseDouble(next());
	}

	static String next() throws Exception {
		while (true) {
			if (tokenizer.hasMoreTokens()) {
				return tokenizer.nextToken();
			}
			String s = br.readLine();
			if (s == null) {
				return null;
			}
			tokenizer = new StringTokenizer(s);
		}
	}
}