#include <bits/stdc++.h>
using namespace std;
struct Info {
  int previous_element;
  int next_element;
};
Info info[2000000];
string str;
void init() {
  int n = str.size();
  for (int i = 0; i < n; i++) {
    info[i].previous_element = i - 1;
    info[i].next_element = i + 1;
  }
}
bool cut[2000000];
int solve() {
  int n = str.size();
  vector<int> currentCutSet;
  for (int i = 0; i < n; i++) {
    if (i == 0) {
      if (str[i] != str[i + 1]) {
        currentCutSet.push_back(i);
      }
    } else if (i == n - 1) {
      if (str[i] != str[i - 1]) {
        currentCutSet.push_back(i);
      }
    } else {
      if (str[i] != str[i - 1] || str[i] != str[i + 1]) {
        currentCutSet.push_back(i);
      }
    }
  }
  int turn = 0;
  while (currentCutSet.size()) {
    turn++;
    set<int> tempCutSet;
    for (int i = 0; i < currentCutSet.size(); i++) {
      int lastUnCutSet = info[currentCutSet[i]].previous_element;
      if (i == currentCutSet.size() - 1 ||
          info[currentCutSet[i]].next_element != currentCutSet[i + 1]) {
        int nw = info[currentCutSet[i]].next_element;
        info[nw].previous_element = lastUnCutSet;
        if (lastUnCutSet != -1) {
          info[lastUnCutSet].next_element = nw;
          if (nw != n) {
            if (str[nw] != str[lastUnCutSet]) {
              tempCutSet.insert(nw);
              tempCutSet.insert(lastUnCutSet);
            }
          }
        }
        lastUnCutSet = nw;
      } else {
        int nw = info[currentCutSet[i]].next_element;
        info[nw].previous_element = lastUnCutSet;
        if (lastUnCutSet != -1) {
          info[lastUnCutSet].next_element = nw;
        }
      }
    }
    currentCutSet.clear();
    for (auto v : tempCutSet) currentCutSet.push_back(v);
  }
  return turn;
}
int main() {
  cin >> str;
  init();
  cout << solve() << endl;
}
