Cursor Distance

There is a string $s$ of lowercase English letters. A cursor is positioned on one of the characters. The cursor can be moved with the following operation: choose a letter $c$ and a direction (left or right). The cursor is then moved to the closest occurence of $c$ in the chosen direction. If there is no letter $c$ in that direction, the cursor stays in place. For example, if $s = \mathtt{abaab}$ with the cursor on the second character ($\mathtt{a[b]aab}$), then:

  • moving to the closest letter $\mathtt{a}$ to the left places the cursor on the first character ($\mathtt{[a]baab}$);
  • moving to the closest letter $\mathtt{a}$ to the right places the cursor the third character ($\mathtt{ab[a]ab}$);
  • moving to the closest letter $\mathtt{b}$ to the right places the cursor on the fifth character ($\mathtt{abaa[b]}$);
  • any other operation leaves the cursor in place.

Let $\mathrm{dist}(i, j)$ be the smallest number of operations needed to move the cursor from the $i$-th character to the $j$-th character. Compute $\displaystyle \sum_{i = 1}^n \sum_{j = 1}^n \mathrm{dist}(i, j)$.Input

The only line contains a non-empty string $s$ of at most $10^5$ lowercase English letters.Output

Print a single integer $\displaystyle \sum_{i = 1}^n \sum_{j = 1}^n \mathrm{dist}(i, j)$.

Examples input

abcde

output

20

input

abacaba

output

58

Note

In the first sample case, $\mathrm{dist}(i, j) = 0$ for any pair $i = j$, and $1$ for all other pairs.

Solution:

#undef _GLIBCXX_DEBUG

#include <bits/stdc++.h>

using namespace std;

template <typename A, typename B>
string to_string(pair<A, B> p);

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string& s) {
return '"' + s + '"';
}

string to_string(const char* s) {
return to_string((string) s);
}

string to_string(bool b) {
return (b ? "true" : "false");
}

string to_string(vector<bool> v) {
bool first = true;
string res = "{";
for (int i = 0; i < static_cast<int>(v.size()); i++) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(v[i]);
}
res += "}";
return res;
}

template <size_t N>
string to_string(bitset<N> v) {
string res = "";
for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
}
return res;
}

template <typename A>
string to_string(A v) {
bool first = true;
string res = "{";
for (const auto &x : v) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(x);
}
res += "}";
return res;
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
cerr << " " << to_string(H);
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  string foo;
  cin >> foo;
vector<int> s(foo.size());
int n = (int) s.size();
for (int i = 0; i < n; i++) {
    s[i] = (int) (foo[i] - 'a');
  }
  const int ALPHA = 26;
  vector<vector<int>> prev(n, vector<int>(ALPHA));
for (int c = 0; c < ALPHA; c++) {
    prev[0] = -1;
  }
  for (int i = 1; i < n; i++) {
    prev[i] = prev[i - 1];
    prev[i][s[i - 1]] = i - 1;
  }
  vector<vector<int>> next(n, vector<int>(ALPHA));
for (int c = 0; c < ALPHA; c++) {
    next[n - 1] = n;
  }
  for (int i = n - 2; i >= 0; i--) {
next[i] = next[i + 1];
next[i][s[i + 1]] = i + 1;
}
vector<vector<int>> prev_order(n, vector<int>(ALPHA));
for (int i = 0; i < n; i++) {
    iota(prev_order[i].begin(), prev_order[i].end(), 0);
    sort(prev_order[i].begin(), prev_order[i].end(), [&](int x, int y) {
      return prev[i][x] > prev[i][y];
});
}
vector<vector<int>> next_order(n, vector<int>(ALPHA));
for (int i = 0; i < n; i++) {
    iota(next_order[i].begin(), next_order[i].end(), 0);
    sort(next_order[i].begin(), next_order[i].end(), [&](int x, int y) {
      return next[i][x] < next[i][y];
    });
  }
  auto Submask = [&](int A, int B) {
    return ((A & B) == A);
  };
  vector<long long> res(n, n - 1);
vector<int> subset(n);
vector<int> L(n), R(n);
for (int i = 0; i < n; i++) {
    subset[i] = (1 << s[i]);
    L[i] = i;
    R[i] = i;
  }
  int real_alpha = 0;
  for (int i = 0; i < n; i++) {
    real_alpha |= subset[i];
  }
  real_alpha = __builtin_popcount(real_alpha);
  const int LOG = 19;
  vector<vector<int>> jumpL(n, vector<int>(LOG, 0));
vector<vector<int>> jumpR(n, vector<int>(LOG, n - 1));
vector<int> cntJumpL(n);
vector<int> cntJumpR(n);
vector<vector<long long>> sumJumpL(n, vector<long long>(LOG, 0));
vector<vector<long long>> sumJumpR(n, vector<long long>(LOG, 0));
vector<int> prev_subset(n, 0);
vector<int> next_subset(n, 0);
for (int pc = 1; pc <= real_alpha; pc++) {
    for (int i = 0; i < n; i++) {
      if (prev[i][prev_order[i][pc - 1]] != -1) {
        prev_subset[i] |= (1 << prev_order[i][pc - 1]);
      }
      if (next[i][next_order[i][pc - 1]] != n) {
        next_subset[i] |= (1 << next_order[i][pc - 1]);
      }
    }
    cntJumpL[0] = n;
    for (int i = 1; i < n; i++) {
      jumpL[i][0] = max(0, prev[i][prev_order[i][pc - 1]]);
      if (jumpL[i][0] == 0) {
        cntJumpL[i] = n;
      } else {
        if (!Submask(prev_subset[jumpL[i][0]], prev_subset[i])) {
          cntJumpL[i] = 1;
        } else {
          cntJumpL[i] = cntJumpL[jumpL[i][0]] + 1;
        }
      }
      sumJumpL[i][0] = jumpL[i][0];
    }
    cntJumpR[n - 1] = n;
    for (int i = n - 2; i >= 0; i--) {
jumpR[i][0] = min(n - 1, next[i][next_order[i][pc - 1]]);
if (jumpR[i][0] == n - 1) {
cntJumpR[i] = n;
} else {
if (!Submask(next_subset[jumpR[i][0]], next_subset[i])) {
cntJumpR[i] = 1;
} else {
cntJumpR[i] = cntJumpR[jumpR[i][0]] + 1;
}
}
sumJumpR[i][0] = n - 1 - jumpR[i][0];
}
//    debug(cntJumpR);
//    debug(next_subset);
vector<int> jumps(n);
int max_jumps = 0;
for (int i = 0; i < n; i++) {
      if (__builtin_popcount(subset[i]) != pc) {
        continue;
      }
      int cntL = 0;
      int cntR = 0;
      if (Submask(prev_subset[L[i]], subset[i]) || L[i] == 0) {
        cntL = max(0, cntJumpL[L[i]]);
      }
      if (Submask(next_subset[R[i]], subset[i]) || R[i] == n - 1) {
        cntR = max(0, cntJumpR[R[i]]);
      }
      jumps[i] = (pc == real_alpha ? max(cntL, cntR) : min(cntL, cntR));
      max_jumps = max(max_jumps, jumps[i]);
    }
    int CUR_LOG = 0;
    while ((1 << CUR_LOG) <= max_jumps) {
      CUR_LOG += 1;
    }
    for (int j = 1; j < CUR_LOG; j++) {
      for (int i = 0; i < n; i++) {
        jumpL[i][j] = jumpL[jumpL[i][j - 1]][j - 1];
        sumJumpL[i][j] = sumJumpL[i][j - 1] + sumJumpL[jumpL[i][j - 1]][j - 1];
        jumpR[i][j] = jumpR[jumpR[i][j - 1]][j - 1];
        sumJumpR[i][j] = sumJumpR[i][j - 1] + sumJumpR[jumpR[i][j - 1]][j - 1];
      }
    }
    for (int i = 0; i < n; i++) {
      if (__builtin_popcount(subset[i]) != pc) {
        continue;
      }
//      debug(pc, subset[i], i, L[i], R[i], cntL, cntR, jumps);
      for (int j = 0; j < CUR_LOG; j++) {
        if (jumps[i] & (1 << j)) {
          res[i] += sumJumpL[L[i]][j];
          L[i] = jumpL[L[i]][j];
          res[i] += sumJumpR[R[i]][j];
          R[i] = jumpR[R[i]][j];
        }
      }
      int newL = L[i];
      int newR = R[i];
      for (int c = 0; c < ALPHA; c++) {
        if (subset[i] & (1 << c)) {
          newL = min(newL, prev[L[i]]);
          newR = max(newR, next[R[i]]);
        }
      }
      newL = max(newL, 0);
      newR = min(newR, n - 1);
      L[i] = newL;
      R[i] = newR;
      res[i] += newL + (n - 1 - newR);
      int new_subset = 0;
      for (int c = 0; c < ALPHA; c++) {
        if (s[L[i]] == c || next[L[i]] <= R[i]) {
          new_subset |= (1 << c);
        }
      }
//      debug(pc, i, L[i], R[i], subset[i], new_subset);
      assert(pc == real_alpha || __builtin_popcount(new_subset) > pc);
subset[i] = new_subset;
}
}
//  debug(subset, L, R, res);
long long ans = 0;
for (int i = 0; i < n; i++) {
    ans += res[i];
  }
  cout << ans << '\n';
  cerr << "time = " << clock() << " ms" << '\n';
  return 0;
}