#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000005;
int n, ans;
int sum[maxn];
char s[maxn];
set<int> pos0, pos1;
namespace Segtree {
int mn[maxn * 4], mx[maxn * 4], tag[maxn * 4];
void pushup(int cur) {
  mn[cur] = min(mn[cur << 1], mn[cur << 1 | 1]);
  mx[cur] = max(mx[cur << 1], mx[cur << 1 | 1]);
}
void build(int cur, int l, int r) {
  if (l == r) {
    mn[cur] = mx[cur] = sum[l];
    return;
  }
  int mid = l + r >> 1;
  build(cur << 1, l, mid);
  build(cur << 1 | 1, mid + 1, r);
  pushup(cur);
}
void apply(int cur, int val) {
  mn[cur] += val;
  mx[cur] += val;
  tag[cur] += val;
}
void pushdown(int cur) {
  if (tag[cur]) {
    apply(cur << 1, tag[cur]);
    apply(cur << 1 | 1, tag[cur]);
    tag[cur] = 0;
  }
}
void update(int cur, int l, int r, int vl, int vr, int val) {
  if (l >= vl && r <= vr) {
    apply(cur, val);
    return;
  }
  pushdown(cur);
  int mid = l + r >> 1;
  if (mid >= vl) update(cur << 1, l, mid, vl, vr, val);
  if (mid < vr) update(cur << 1 | 1, mid + 1, r, vl, vr, val);
  pushup(cur);
}
int queryL(int cur, int l, int r, int val) {
  if (mn[cur] >= val) return r + 1;
  if (l == r) return l;
  pushdown(cur);
  int mid = l + r >> 1;
  if (mn[cur << 1] >= val)
    return queryL(cur << 1 | 1, mid + 1, r, val);
  else
    return queryL(cur << 1, l, mid, val);
}
int queryR(int cur, int l, int r, int val) {
  if (mn[cur] >= val) return l - 1;
  if (l == r) return r;
  pushdown(cur);
  int mid = l + r >> 1;
  if (mn[cur << 1 | 1] >= val)
    return queryR(cur << 1, l, mid, val);
  else
    return queryR(cur << 1 | 1, mid + 1, r, val);
}
}  // namespace Segtree
int main() {
  scanf("%s", s + 1);
  n = strlen(s + 1);
  for (int i = 1; i <= n; i++) {
    if (s[i] == '0')
      sum[i] = sum[i - 1] - 1;
    else if (s[i] == '1')
      sum[i] = sum[i - 1] + 1;
    else
      sum[i] = sum[i - 1] - 1, pos0.insert(i);
  }
  Segtree::build(1, 0, n);
  ans = Segtree::mx[1] - Segtree::mn[1];
  for (int i = Segtree::mn[1]; i <= 0; i++) {
    int p = Segtree::queryL(1, 0, n, i);
    if (p <= n) {
      set<int>::iterator it = pos0.upper_bound(p);
      if (it != pos0.begin()) {
        --it;
        Segtree::update(1, 0, n, *it, n, 2);
        pos1.insert(*it);
        pos0.erase(it);
      } else
        break;
    }
    int q = Segtree::queryR(1, 0, n, i + 2);
    if (q >= 1) {
      set<int>::iterator it = pos1.upper_bound(q);
      if (it != pos1.end()) {
        Segtree::update(1, 0, n, *it, n, -2);
        pos0.insert(*it);
        pos1.erase(it);
      }
    }
    ans = min(ans, Segtree::mx[1] - Segtree::mn[1]);
  }
  printf("%d\n", ans);
  return 0;
}
