#include <bits/stdc++.h>
using namespace std;
template <class T>
bool chmax(T& a, const T& b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
bool chmin(T& a, const T& b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
T div_floor(T a, T b) {
  if (b < 0) a *= -1, b *= -1;
  return a >= 0 ? a / b : (a + 1) / b - 1;
}
template <class T>
T div_ceil(T a, T b) {
  if (b < 0) a *= -1, b *= -1;
  return a > 0 ? (a - 1) / b + 1 : a / b;
}
constexpr long long mod = 1000000007;
constexpr long long INF = mod * mod;
constexpr int MAX = 100010;
int main() {
  string s;
  cin >> s;
  int n = s.size();
  set<tuple<int, int, char>> S;
  for (int l = 0; l < n;) {
    int r = l;
    while (r < n && s[l] == s[r]) ++r;
    S.insert({l, r - 1, s[l]});
    l = r;
  }
  int ans = 0;
  while (S.size() > 1) {
    ++ans;
    vector<tuple<int, int, char>> v;
    set<tuple<int, int, char>> T;
    for (auto it = S.begin(); it != S.end(); ++it) {
      auto [l, r, c] = *it;
      if (it == S.begin()) {
        --r;
      } else if (next(it) == S.end()) {
        ++l;
      } else {
        ++l;
        --r;
      }
      if (l <= r) v.push_back({l, r, c});
    }
    for (int l = 0; l < v.size();) {
      int r = l;
      while (r < v.size() && get<2>(v[l]) == get<2>(v[r])) {
        ++r;
      }
      T.insert({get<0>(v[l]), get<1>(v[r - 1]), get<2>(v[l])});
      l = r;
    }
    swap(S, T);
  }
  printf("%d\n", ans);
}
