// atcoder AGC 20200607 B
#include <bits/stdc++.h>
//#define inf 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f3f
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define inv(x) Power(x, mod - 2)
#define fi first
#define se second
#define MP make_pair
#define PB push_back

typedef std::vector<int> Poly;
typedef std::pair<int, int> Pair;
typedef unsigned long long ull;
typedef long double ld;
typedef long long ll;

const int maxn = 1000000, maxm = 1e5, MAX = 1e6 + 5, mod = 998244353;
// template{{{
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 = (ll)ans * x % Mod;
        x = (ll)x * x % Mod, y >>= 1;
    }
    return ans;
}

/*char buf[1<<23],obuf[1<<23],*p1=buf,*p2=buf, *O = obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
void print(int x) {
    if(x > 9) print(x / 10);
    *O++=x%10+'0';
} */

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 (ll)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() {
#ifdef local
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
    freopen("log", "w", stderr);
#endif

    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;
    }

#define Push(i) que.push(Pair(abs((l0[i] + r0[i]) - (l1[i] + r1[i])), i))
    std::priority_queue<Pair> que;
    for (int i = 1; i <= n; ++i)
        if (s[i] == '?' && (s[i - 1] != '?' || s[i + 1] != '?'))
            Push(i);

    while (!que.empty()) {
        int u = que.top().second;
        que.pop();
        if (s[u] != '?')
            continue;
        if (l0[u] + r0[u] > l1[u] + r1[u])
            s[u] = '1', Add(u, 1);
        else
            s[u] = '0', 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]), Push(l);
        chkmax(l0[r], -query(u, r) + l0[u]);
        chkmax(l1[r], query(u, r) + l1[u]), Push(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;
}

Measured memory_bytes: 71116