注意事项:无。
后缀自动机
代码:
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
| int cntnd, root, last, son[MAXnd + 10][26 + 2], fail[MAXnd + 10], mxlen[MAXnd + 10]; int cntep[MAXnd + 10]; void init() { cntnd = root = last = 1; } void extend(int ch) { int a, b, c; a = c = last; b = last = ++cntnd; mxlen[b] = mxlen[a] + 1; cntep[b] = 1; for (; c && son[c][ch] == 0; c = fail[c]) son[c][ch] = b; if (c == 0) { fail[b] = root; } else { int d = son[c][ch]; if (mxlen[d] == mxlen[c] + 1) { fail[b] = d; } else { int e = ++cntnd; memcpy(son[e], son[d], sizeof(son[e])); fail[e] = fail[d]; mxlen[e] = mxlen[c] + 1; fail[b] = fail[d] = e; for (; c && son[c][ch] == d; c = fail[c]) son[c][ch] = e; } } }
|
Luogu P3804 【模板】后缀自动机 (SAM)
代码:
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
| const int MAXnd = MAXn * 2; int head[MAXnd + 10], cntnex, nex[MAXnd + 10], to[MAXnd + 10]; void connect(int u, int v) { nex[++cntnex] = head[u]; head[u] = cntnex; to[cntnex] = v; }
int cntnd, root, last, son[MAXnd + 10][26 + 2], fail[MAXnd + 10], mxlen[MAXnd + 10]; int cntep[MAXnd + 10]; void init() { cntnd = root = last = 1; } void extend(int ch) { int a, b, c; a = c = last; b = last = ++cntnd; mxlen[b] = mxlen[a] + 1; cntep[b] = 1; for (; c && son[c][ch] == 0; c = fail[c]) son[c][ch] = b; if (c == 0) { fail[b] = root; } else { int d = son[c][ch]; if (mxlen[d] == mxlen[c] + 1) { fail[b] = d; } else { int e = ++cntnd; memcpy(son[e], son[d], sizeof(son[e])); fail[e] = fail[d]; mxlen[e] = mxlen[c] + 1; fail[b] = fail[d] = e; for (; c && son[c][ch] == d; c = fail[c]) son[c][ch] = e; } } } void buildfailtree() { for (int i = 1; i <= cntnd; ++i) { if (i == root) 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]]; } if (cntep[cur] > 1) ans = max(ans, (ll)cntep[cur] * mxlen[cur]); }
int len; char str[MAXn + 10]; signed main() { init(); scanf("%s", str + 1); len = strlen(str + 1); for (int i = 1; i <= len; ++i) { extend(str[i] - 'a'); } buildfailtree(); dfs(root); printf("%lld\n", ans); return 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 28 29 30
| int cntnd, root, last, son[MAXnd + 10][26 + 2], fail[MAXnd + 10], mxlen[MAXnd + 10]; void init() { cntnd = root = last = 1; } void extend(int ch = -1) { int a, b, c; a = c = last; b = last = ++cntnd; mxlen[b] = mxlen[a] + 1; if (ch == -1) { fail[b] = root; return; } for (; c && son[c][ch] == 0; c = fail[c]) son[c][ch] = b; if (c == 0) { fail[b] = root; } else { int d = son[c][ch]; if (mxlen[d] == mxlen[c] + 1) { fail[b] = d; } else { int e = ++cntnd; copy(begin(son[d]), end(son[d]), begin(son[e])); fail[e] = fail[d]; mxlen[e] = mxlen[c] + 1; fail[b] = fail[d] = e; for (; c && son[c][ch] == d; c = fail[c]) son[c][ch] = e; } } }
|
Luogu P6139 【模板】广义后缀自动机(广义 SAM)
代码:
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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| #include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXn = 4e5; const int MAXlen = 1e6; const int MAXsumlen = 1e6;
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...); }
const int MAXnd = MAXn + MAXsumlen * 2; int head[MAXnd + 10], cntnex, nex[MAXnd + 10], to[MAXnd + 10]; void connect(int u, int v) { nex[++cntnex] = head[u]; head[u] = cntnex; to[cntnex] = v; }
int cntnd, root, last, son[MAXnd + 10][26 + 2], fail[MAXnd + 10], mxlen[MAXnd + 10]; void init() { cntnd = root = last = 1; } void extend(int ch = -1) { int a, b, c; a = c = last; b = last = ++cntnd; mxlen[b] = mxlen[a] + 1; if (ch == -1) { fail[b] = root; return; } for (; c && son[c][ch] == 0; c = fail[c]) son[c][ch] = b; if (c == 0) { fail[b] = root; } else { int d = son[c][ch]; if (mxlen[d] == mxlen[c] + 1) { fail[b] = d; } else { int e = ++cntnd; copy(begin(son[d]), end(son[d]), begin(son[e])); fail[e] = fail[d]; mxlen[e] = mxlen[c] + 1; fail[b] = fail[d] = e; for (; c && son[c][ch] == d; c = fail[c]) son[c][ch] = e; } } } void buildfailtree() { for (int i = 1; i <= cntnd; ++i) { if (i == root) continue; connect(fail[i], i); } }
int n; int len[MAXn + 10]; char str[MAXlen + 10]; int suflen[MAXn + 10]; signed main() { init(); read(n); for (int i = 1; i <= n; ++i) { scanf("%s", str + 1); len[i] = strlen(str + 1); for (int j = 1; j <= len[i]; ++j) { extend(str[j] - 'a'); } extend(); } buildfailtree(); ll ans = 0; for (int i = 1; i <= cntnd; ++i) { if (i == root) continue; ans += mxlen[i] - mxlen[fail[i]]; } for (int i = n; i; --i) { suflen[i] = suflen[i + 1] + (len[i] + 1); } for (int i = 1; i <= n; ++i) { ans -= (ll)(len[i] + 1) * (suflen[i + 1] + 1); } printf("%lld\n", ans); return 0; }
|