/* I will wait for you */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <string>
#define make make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 1000010;
const int maxm = 1010;
const int maxs = 26;
const int inf = 0x3f3f3f3f;
const int P = 1000000007;
const double error = 1e-9;
inline ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
f = (ch == '-' ? -1 : 1), ch = getchar();
while (ch >= '0' && ch <= '9')
x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
struct Sa
{
int k[2],pos;
bool operator != (const Sa b) {
return k[0] != b.k[0] || k[1] != b.k[1];
}
} x[maxn], y[maxn];
int n, c[maxn], rank[maxn], sa[maxn], q[maxn];
ll ans, up[maxn], down[maxn], hi[maxn];
char s[maxn];
void work()
{
for (int i = 0; i <= n; i++)
c[i] = 0;
for (int i = 0; i < n; i++)
c[s[i]]++;
for (int i = 1; i <= n; i++)
c[i] += c[i - 1];
for (int i = 0; i < n; i++)
rank[i] = c[s[i] - 1];
for (int k = 1; k < n; k <<= 1) {
for (int i = 0; i < n; i++) {
x[i].k[0] = rank[i];
x[i].k[1] = (i + k < n) ?
rank[i + k] + 1: 0;
x[i].pos = i;
}
for (int m = 1; m >= 0; m--) {
for (int i = 0; i <= n; i++)
c[i] = 0;
for (int i = 0; i < n; i++)
c[x[i].k[m]]++;
for (int i = 1; i <= n; i++)
c[i] += c[i - 1];
for (int i = n - 1; i >= 0; i--)
y[--c[x[i].k[m]]] = x[i];
for (int i = 0; i < n; i++)
x[i] = y[i];
}
for (int i = 0; i < n; i++)
rank[x[i].pos] = i ? rank[x[i - 1].pos]
+ (x[i] != x[i - 1]) : 0;
}
for (int i = 0; i < n; i++) sa[rank[i]] = i;
for (int i = 0, h = 0; i < n; i++) {
h = max(h - 1, 0);
for (; rank[i] && s[i + h] ==
s[sa[rank[i] - 1] + h]; h++);
hi[rank[i]] = rank[i] ? h : 0;
}
}
int main()
{
scanf("%s", s), n = strlen(s);
for (int i = 0; i < n; i++)
s[i] -= 'a' - 1;
work();
q[0] = 0;
for (int i = 1, top = 0; i < n; i++) {
while (top && hi[q[top]] >= hi[i]) top--;
int t = q[top];
up[i] = up[t] + (i - t) * hi[i];
q[++top] = i;
}
q[0] = n;
for (int i = n - 1, top = 0; i >= 0; i--) {
while (top && hi[q[top]] >= hi[i]) top--;
int t = q[top];
down[i] = down[t] + (t - i) * hi[i];
q[++top] = i;
}
ans = (ll) n * (n + 1) * (n - 1) / 2;
for (int i = 0; i < n; i++) ans -= up[i] + down[i];
printf("%lld\n", ans);
return 0;
}
BZOJ3238【后缀数组】【单调栈】
最新推荐文章于 2018-05-27 19:51:10 发布