注意事项:

  1. 函数 buildi-len[]-1 可能会超出字符串的下标范围,到达下标 0,需要特判。
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
int cntnd, rootodd, rooteve;
int son[MAXlenb + 10][26 + 2], fail[MAXlenb + 10], len[MAXlenb + 10];
int cntep[MAXlenb + 10];
void build(int lenb, char *b) {
cntnd = 2;
rootodd = 1; len[rootodd] = -1;
rooteve = 2; fail[rooteve] = rootodd; len[rooteve] = 0;
int j = rootodd;
for (int i = 1; i <= lenb; ++i) {
while (i - len[j] - 1 == 0 || b[i - len[j] - 1] != b[i]) j = fail[j];
if (son[j][b[i]] == 0) {
int nwj = son[j][b[i]] = ++cntnd;
len[nwj] = len[j] + 2;
int k;
if (j == rootodd) {
k = rooteve;
} else {
k = fail[j];
while (i - len[k] - 1 == 0 || b[i - len[k] - 1] != b[i]) k = fail[k];
k = son[k][b[i]];
}
fail[nwj] = k;
}
j = son[j][b[i]];
++cntep[j];
}
}

Luogu P3649 [APIO2014] 回文串

代码:

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
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXlenb = 3e5;

template <typename T>
inline void read(T &a) {
char c;for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar());bool f = c == '-';T x = f ? 0 : (c ^ '0');for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) {x = x * 10 + (c ^ '0');}a = f ? -x : x;
}
template <typename T, typename ...Argv>
inline void read(T &a, Argv &...argv) {
read(a), read(argv...);
}

int head[MAXlenb + 10], cntnex, nex[MAXlenb + 10], to[MAXlenb + 10];
inline void connect(int u, int v) {
nex[++cntnex] = head[u];
head[u] = cntnex;
to[cntnex] = v;
}

int cntnd, rootodd, rooteve;
int son[MAXlenb + 10][26 + 2], fail[MAXlenb + 10], len[MAXlenb + 10];
int cntep[MAXlenb + 10];
void build(int lenb, char *b) {
cntnd = 2;
rootodd = 1; len[rootodd] = -1;
rooteve = 2; fail[rooteve] = rootodd; len[rooteve] = 0;
int j = rootodd;
for (int i = 1; i <= lenb; ++i) {
while (i - len[j] - 1 == 0 || b[i - len[j] - 1] != b[i]) j = fail[j];
if (son[j][b[i]] == 0) {
int nwj = son[j][b[i]] = ++cntnd;
len[nwj] = len[j] + 2;
int k;
if (j == rootodd) {
k = rooteve;
} else {
k = fail[j];
while (i - len[k] - 1 == 0 || b[i - len[k] - 1] != b[i]) k = fail[k];
k = son[k][b[i]];
}
fail[nwj] = k;
}
j = son[j][b[i]];
++cntep[j];
}
}
void buildfailtree() {
for (int i = 1; i <= cntnd; ++i) {
if (i == rootodd) continue;
connect(fail[i], i);
}
}
ll ans;
void dfs(int cur) {
for (int i = head[cur]; i; i = nex[i]) {
dfs(to[i]);
cntep[cur] += cntep[to[i]];
}
ans = max(ans, (ll)len[cur] * cntep[cur]);
}

int lenb; char b[MAXlenb + 10];
signed main() {
scanf("%s", b + 1);
lenb = strlen(b + 1);
for (int i = 1; i <= lenb; ++i) b[i] -= 'a';
build(lenb, b);
buildfailtree();
dfs(rootodd);
printf("%lld\n", ans);
return 0;
}