后缀自动机
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 2e6 + 5;
struct Edge {
int n, t;
}e[N];
int h[N], edc;
void Add(int x, int y) {
e[++edc] = (Edge) {h[x], y}; h[x] = edc;
}
struct Tree {
int f, c[26];
}t[N];
int n, sz[N], len[N], lt, trc, ans;
char s[N];
void Dfs(int x) {
for (int i = h[x], y; i; i = e[i].n)
Dfs(y = e[i].t), sz[x] += sz[y];
if (sz[x] > 1) ans = std::max(ans, sz[x] * len[x]);
}
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
lt = trc = 1;
for (int i = 1; i <= n; ++i) {
int x = lt, c = s[i] - 'a', y, z;
len[lt = ++trc] = len[x] + 1; sz[lt] = 1;
for (; x && !t[x].c[c]; x = t[x].f) t[x].c[c] = lt;
if (!x) t[lt].f = 1;
else if (len[y = t[x].c[c]] == len[x] + 1) t[lt].f = y;
else {
t[z = ++trc] = t[y]; len[z] = len[x] + 1;
t[y].f = t[lt].f = z;
for (; x && t[x].c[c] == y; x = t[x].f) t[x].c[c] = z;
}
}
for (int i = 2; i <= trc; ++i)
Add(t[i].f, i);
Dfs(1);
printf("%d
", ans);
return 0;
}
广义后缀自动机
#include <cstdio>
#include <cstring>
const int N = 2e6 + 5;
struct Sam {
int f, s[26];
}t[N];
int m, n, len[N], trc = 1;
long long ans;
char s[N];
int main() {
scanf("%d", &m);
while (m--) {
scanf("%s", s + 1);
int rt = 1, n = strlen(s + 1);
for (int i = 1; i <= n; ++i) {
int x = rt, c = s[i] - 'a', y;
if (t[x].s[c] && len[rt = y = t[x].s[c]] > len[x] + 1) {
t[rt = ++trc] = t[y]; len[trc] = len[x] + 1; t[y].f = trc;
for (; x && t[x].s[c] == y; x = t[x].f) t[x].s[c] = trc;
}
else {
len[rt = ++trc] = len[x] + 1;
for (; x && !t[x].s[c]; x = t[x].f) t[x].s[c] = rt;
if (!x) t[rt].f = 1;
else if (len[y = t[x].s[c]] == len[x] + 1) t[rt].f = y;
else {
t[++trc] = t[y]; len[trc] = len[x] + 1; t[rt].f = t[y].f = trc;
for (; x && t[x].s[c] == y; x = t[x].f) t[x].s[c] = trc;
}
}
}
}
for (int i = 2; i <= trc; ++i)
ans += len[i] - len[t[i].f];
printf("%lld
", ans);
return 0;
}