题目
分析
我终于 学会 sam 了
这个东西我们考虑再parent树上dp就好
代码
#include <bits/stdc++.h>
typedef long long ll;
const int N = 500005;
char s[N];
int max[N * 2],fa[N * 2];
int ch[N * 2][30];
int root,cnt,last;
int w[N * 2], f[N * 2];
void extend(int x)
{
int p,q,np,nq;
p = last, last = np = ++cnt;
max[np] = max[p] + 1;
w[np] = f[np] = 1;
for (; !ch[p][x] && p; p = fa[p])
ch[p][x] = np;
if (!p)
fa[np] = root;
else
{
q = ch[p][x];
if (max[p] + 1 == max[q])
{
fa[np] = q;
}
else
{
nq = ++cnt;
max[nq] = max[p] + 1;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
fa[nq] = fa[q];
fa[q] = fa[np] = nq;
for (; ch[p][x] == q; p = fa[p])
ch[p][x] = nq;
}
}
}
int n;
int b[N * 2],c[N * 2];
ll cal()
{
for (int i = 1; i <= cnt; i++)
b[max[i]]++;
for (int i = 1; i <= n; i++)
b[i] += b[i - 1];
for (int i = 1; i <= cnt; i++)
c[b[max[i]]--] = i;
for (int i = cnt; i >= 1; i--)
f[fa[c[i]]] += f[c[i]];
ll ans = 0;
for (int i = 1; i <= cnt; i++)
{
ans += 1ll * w[fa[i]] * f[i] * max[fa[i]];
w[fa[i]] += f[i];
}
return ans;
}
int main()
{
scanf("%s", s + 1);
n = strlen(s + 1);
last = cnt = root = 1;
for (int i = 1; i <= n; i++)
extend(s[i] - 'a');
ll ans = 0;
for (int i = 1; i <= n; i++)
ans += (ll)i * (n - 1);
printf("%lld\n", ans - 2ll * cal());
}