#include <bits/stdc++.h>
using namespace std;
template <class T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << '{';
  for (int i = (0), __i = (((int)(vec).size())); i < __i; i++) {
    os << vec[i];
    if (i + 1 != ((int)(vec).size())) os << ',';
  }
  os << '}';
  return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &par) {
  os << '(' << par.first << ',' << par.second << ')';
  return os;
}
int gcd(int x, int y) { return y ? gcd(y, x % y) : abs(x); }
template <class T>
T sqr(T x) {
  return x * x;
}
const long long MOD = 1e9 + 7;
long long bin_pow(long long base, long long p) {
  if (p == 1) return base;
  if (p % 2 == 0) {
    long long t = bin_pow(base, p / 2);
    return t * t % MOD;
  } else
    return bin_pow(base, p - 1) * base % MOD;
}
long long inverse_element(long long x) { return bin_pow(x, MOD - 2); }
long long add(long long a, long long b) { return (a + b) % MOD; }
long long sub(long long a, long long b) { return (MOD + a - b) % MOD; }
long long divide(long long a, long long b) {
  return a * inverse_element(b) % MOD;
}
long long mult(long long a, long long b) { return (a * b) % MOD; }
int intr[1010101];
int nxt[1010101];
int prv[1010101];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  string s;
  cin >> s;
  queue<pair<int, int> > que[2];
  bool cur = false;
  int n = s.length();
  for (int i = (0), __i = (n); i < __i; i++) {
    nxt[i] = i + 1;
    prv[i] = i - 1;
  }
  nxt[n - 1] = -1;
  prv[0] = -1;
  int start = -1;
  bool move = false;
  for (int i = (0), __i = (n); i < __i; i++) {
    if ((i > 0 && s[i - 1] != s[i]) || (i < n - 1 && s[i + 1] != s[i])) {
      if (start == -1) {
        start = i;
      }
      intr[i] = 1;
      move = true;
    } else {
      if (start != -1) {
        prv[i] = start - 1;
        if (start > 0) {
          que[cur].push({start - 1, i});
          nxt[start - 1] = i;
        }
        start = -1;
      }
    }
  }
  long long res = move;
  while (true) {
    if (que[cur].empty()) break;
    move = false;
    while (!que[cur].empty()) {
      pair<int, int> u = que[cur].front();
      que[cur].pop();
      if (intr[u.first] != 1 && intr[u.second] != 1) {
        bool changed = false;
        int right = u.second;
        while (right != -1 &&
               ((nxt[right] != -1 && s[right] != s[nxt[right]]) ||
                (prv[right] != -1 && s[right] != s[prv[right]]))) {
          intr[right] = 1;
          right = nxt[right];
          move = changed = true;
        }
        int left = u.first;
        while (left != -1 && ((nxt[left] != -1 && s[left] != s[nxt[left]]) ||
                              (prv[left] != -1 && s[left] != s[prv[left]]))) {
          intr[left] = 1;
          left = prv[left];
          move = changed = true;
        }
        if (changed) {
          if (right != -1) prv[right] = left;
          if (left != -1) nxt[left] = right;
          if (left != -1 && right != -1) que[!cur].push({left, right});
        }
      }
    }
    cur = !cur;
    if (move) res++;
  }
  cout << res;
  return 0;
}
