#include <bits/stdc++.h>
const int maxn = 1000000, maxm = 1e5, MAX = 1e6 + 5, mod = 998244353;
const long double Pi = 3.14159265358979323846l, Eps = 1e-4;
template <class T>
inline bool equal(T x, T y) {
  return fabs(x - y) < Eps;
}
inline int add(int x, int y) {
  x += y;
  return x >= mod ? x - mod : x;
};
inline void inc(int &x, int y) {
  x += y;
  x -= (x >= mod ? mod : 0);
}
inline int mul(int x, int y) { return 1ll * x * y % mod; }
inline int Power(int x, int y, int Mod = mod) {
  int ans = 1;
  while (y) {
    if (y & 1) ans = (long long)ans * x % Mod;
    x = (long long)x * x % Mod, y >>= 1;
  }
  return ans;
}
template <class T>
inline T input() {
  T x;
  char ch;
  bool flag = false;
  while (!isdigit(ch = getchar())) flag |= ch == '-';
  for (x = ch ^ 48; isdigit(ch = getchar()); x = x * 10 + (ch ^ 48))
    ;
  return flag ? -x : x;
}
template <class T>
inline bool chkmin(T &x, T y) {
  x = x < y ? x : y;
  return x == y;
}
template <class T>
inline bool chkmax(T &x, T y) {
  x = x > y ? x : y;
  return x == y;
}
template <class T>
inline T gcd(T x, T y) {
  return !y ? x : gcd(y, x % y);
}
template <class T>
inline T sqrm(T x) {
  return (long long)x * x % mod;
}
template <class T>
inline T sqr(T x) {
  return x * x;
}
struct {
  inline operator int() { return input<int>(); }
  inline operator long long() { return input<long long>(); }
  template <class T>
  inline void operator()(T &x) {
    x = *this;
  }
  template <class T, class... A>
  inline void operator()(T &x, A &...a) {
    x = *this;
    this->operator()(a...);
  }
} read;
int n;
char s[maxn + 5];
int l0[maxn + 5], r0[maxn + 5], l1[maxn + 5], r1[maxn + 5];
std::set<int> S;
int pre(int p) {
  auto it = S.lower_bound(p);
  if (it == S.begin()) return 0;
  return *--it;
}
int nxt(int p) {
  auto it = S.upper_bound(p);
  if (it == S.end()) return 0;
  return *it;
}
int c[maxn + 5];
void Add(int p, int v) {
  for (int i = p; i <= maxn; i += i & -i) c[i] += v;
}
int query(int p) {
  int res = 0;
  for (int i = p; i; i ^= i & -i) res += c[i];
  return res;
}
int query(int l, int r) {
  if (l && l <= r)
    return query(r) - query(l - 1);
  else
    return 0;
}
signed main() {
  scanf("%s", s + 1);
  n = strlen(s + 1);
  for (int i = 1; i <= n; ++i)
    if (s[i] == '?')
      S.insert(i);
    else if (s[i] == '1')
      Add(i, 1);
    else
      Add(i, -1);
  int s0 = 0, s1 = 0;
  for (int i = 1; i <= n; ++i) {
    if (s[i] == '0') {
      ++s0;
      if (s1) --s1;
    } else if (s[i] == '1') {
      ++s1;
      if (s0) --s0;
    } else
      l0[i] = s0, l1[i] = s1, s0 = s1 = 0;
  }
  s0 = 0, s1 = 0;
  for (int i = n; i; --i) {
    if (s[i] == '0') {
      ++s0;
      if (s1) --s1;
    } else if (s[i] == '1') {
      ++s1;
      if (s0) --s0;
    } else
      r0[i] = s0, r1[i] = s1, s0 = s1 = 0;
  }
  std::priority_queue<std::pair<int, int> > que;
  for (int i = 1; i <= n; ++i)
    if (s[i] == '?' && (s[i - 1] != '?' || s[i + 1] != '?'))
      que.push(std::pair<int, int>(std::max(l0[i] + r0[i], l1[i] + r1[i]), i));
  while (!que.empty()) {
    int u = que.top().second, tmp = que.top().first;
    que.pop();
    if (s[u] != '?') continue;
    if (l0[u] + r0[u] > l1[u] + r1[u])
      s[u] = '1', Add(u, 1);
    else if (l0[u] + r0[u] < l1[u] + r1[u])
      s[u] = '0', Add(u, -1);
    else if (tmp)
      que.push(std::pair<int, int>(0, u));
    else
      s[u] = '1', Add(u, 1);
    int l = pre(u), r = nxt(u);
    chkmax(r0[l], -query(l, u) + r0[u]);
    chkmax(r1[l], query(l, u) + r1[u]),
        que.push(
            std::pair<int, int>(std::max(l0[l] + r0[l], l1[l] + r1[l]), l));
    chkmax(l0[r], -query(u, r) + l0[u]);
    chkmax(l1[r], query(u, r) + l1[u]),
        que.push(
            std::pair<int, int>(std::max(l0[r] + r0[r], l1[r] + r1[r]), r));
    S.erase(u);
  }
  int res = 0;
  s0 = s1 = 0;
  for (int i = 1; i <= n; ++i) {
    if (s[i] == '0') {
      chkmax(res, ++s0);
      if (s1) --s1;
    } else if (s[i] == '1') {
      chkmax(res, ++s1);
      if (s0) --s0;
    }
  }
  printf("%d\n", res);
  return 0;
}
