//package practice.pset1;

import java.io.*;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

public class R455D {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        char[] arr = sc.next().toCharArray();
        TreeSet<Segment> set = new TreeSet<>();

        int ii = 0;
        while(ii < arr.length){
            char c = arr[ii];
            int st = ii;
            while(ii+1 < arr.length && arr[ii+1] == c){
                ii++;
            }
            Segment s = new Segment(st, ii-st+1, c);
            set.add(s);
            ii++;
        }

        int cnt = 0;
        while(set.size() > 1){
            cnt++;
            TreeSet<Segment> tmp = new TreeSet<>();
            for (Segment s: set) {
                if(set.higher(s) != null) {
                    s.cnt--;
                }
                if(set.lower(s) != null) {
                    s.cnt--;
                }
                if(s.cnt > 0) {
                    tmp.add(s);
                }
            }

            set.clear();
            Segment cur;
            do{
                cur = tmp.pollFirst();
                while(!tmp.isEmpty() && tmp.first().c == cur.c){
                    cur = merge(cur, tmp.pollFirst());
                }
                if(cur != null)
                    set.add(cur);
            }while(cur != null);
        }

        pw.println(cnt);
        pw.flush();
        pw.close();
    }

    static Segment merge(Segment a, Segment b){
        return new Segment(a.id, a.cnt+b.cnt, a.c);
    }

    static class Segment implements Comparable<Segment>{
        int id, cnt;
        char c;

        public Segment(int id, int cnt, char c) {
            this.id = id;
            this.cnt = cnt;
            this.c = c;
        }

        @Override
        public int compareTo(Segment s) {
            return this.id - s.id;
        }

        public String toString(){
            return id + ": " + cnt + " " + c;
        }
    }


    static int[][] packD(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from) if(f != -1) p[f]++;
        for (int i = 0; i < n; i++) g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) if(from[i] != -1) {g[from[i]][--p[from[i]]] = to[i];}
        return g;
    }

    static void shuffle(int[] a)
    {
        int n = a.length;
        for(int i = 0; i < n; i++)
        {
            int r = i + (int)(Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }

    static class Scanner
    {
        StringTokenizer st; BufferedReader br;
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}
        public Scanner(String s) throws FileNotFoundException {	br = new BufferedReader(new FileReader(new File(s)));}
        public String next() throws IOException {while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());return st.nextToken();}
        public int nextInt() throws IOException {return Integer.parseInt(next());}
        public long nextLong() throws IOException {return Long.parseLong(next());}
        public String nextLine() throws IOException {return br.readLine();}
        public boolean ready() throws IOException {return br.ready();}
    }
}
