注意事项:
- 函数
build 中 i-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; }
|