1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>
#include <unordered_map>

long long one(const std::string &in) {
    long long out = 0;
    long long run;
    char curr = '\0';

    for (char c: in) {
        if (c == curr) {
            run += 1;
        } else {
            curr = c;
            run = 1;
        }
        out += run;
    }

    return out;
}

long long two(const std::string &in) {
    long long out = 0;
    std::unordered_map<int, long long> seen;
    std::unordered_map<int, int> which_it;
    int it = 0;

    for (char a: { 'a', 'b' }) {
        for (char b: { 'b', 'c' }) {
            if (b <= a) { continue; }
            
            int run = 0;
            seen[0] = 1;
            it += 1;
            which_it[0] = it;

            for (char c: in) {
                if (c == a) {
                    run += 1;
                } else if (c == b) {
                    run -= 1;
                } else {
                    it += 1;
                    run = 0;
                }

                if (which_it.count(run) == 1 && which_it[run] == it) {
                    out += seen[run];
                    seen[run] += 1;
                } else {
                    which_it[run] = it;
                    seen[run] = 1;
                }
            }
        }
    }

    return out;
}

struct dat {
    int a = 0;
    int b = 0;
    int c = 0;

    void add(char v) {
        int &to0 = v == 'a' ? a : v == 'b' ? b : c;
        int &to1 = v == 'a' ? b : v == 'b' ? c : a;
        int &to2 = v == 'a' ? c : v == 'b' ? a : b;

        if (to0 == 0 && to1 > 0 && to2 > 0) {
            to1 -= 1;
            to2 -= 1;
        } else {
            to0 += 1;
        }
    }

    bool operator==(const dat &other) const {
        return a == other.a && b == other.b && c == other.c;
    }
};
template<>
struct std::hash<dat>
{
    std::size_t operator()(const dat &d) const
    {
        std::size_t ha = std::hash<int>{}(d.a);
        std::size_t hb = std::hash<int>{}(d.b);
        std::size_t hc = std::hash<int>{}(d.c);
        return ha ^ (hb << 1) ^ (hc >> 1);
    }
};

long long three(const std::string &in) {
    long long out = 0;

    std::unordered_map<dat, long long> seen;
    dat run;
    seen[run] = 1;

    for (char c: in) {
        run.add(c);
        out += seen[run];
        seen[run] += 1;
    }

    return out;
}

int main() {
    std::string in;
    std::cin >> in;

    std::cout << one(in) + two(in) + three(in) << "\n";
}