普通 SAM Code
| #include <cstdio> |
| #include <iostream> |
| #include <cstring> |
| #define IN inline |
| using namespace std; |
| |
| template <typename T> |
| IN void read(T &x) { |
| x = 0; char ch = getchar(); int f = 0; |
| for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar()); |
| for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar()); |
| if (f) x = ~x + 1; |
| } |
| |
| typedef long long LL; |
| const int N = 2e6 + 5; |
| int n; |
| char str[N]; |
| LL ans; |
| |
| struct SAM { |
| int fa[N], len[N], ch[N][26], lst, sz[N], size; |
| IN SAM(){size = lst = 1;} |
| IN void insert(int c) { |
| int p = lst, np = lst = ++size; |
| len[np] = len[p] + 1, sz[np] = 1; |
| for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np; |
| if (!p) {fa[np] = 1; return;} |
| int q = ch[p][c]; |
| if (len[q] == len[p] + 1) {fa[np] = q; return;} |
| int nq = ++size; |
| for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i]; |
| len[nq] = len[p] + 1, fa[nq] = fa[q], fa[np] = fa[q] = nq; |
| for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq; |
| } |
| int h[N], tot; |
| struct edge{int to, nxt;}e[N]; |
| IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;} |
| void buildPT() { |
| for(int i = 2; i <= size; i++) add(fa[i], i); |
| } |
| void dfs(int x) { |
| for(int i = h[x]; i; i = e[i].nxt) dfs(e[i].to), sz[x] += sz[e[i].to]; |
| if (sz[x] > 1) ans = max(ans, (LL)sz[x] * len[x]); |
| } |
| }T; |
| |
| int main() { |
| scanf("%s", str + 1), n = strlen(str + 1); |
| for(int i = 1; i <= n; i++) T.insert(str[i] - 'a'); |
| T.buildPT(), T.dfs(1), printf("%lld\n", ans); |
| } |
广义 SAM Code
| #include <cstdio> |
| #include <iostream> |
| #include <cstring> |
| #include <queue> |
| #define IN inline |
| using namespace std; |
| |
| template <typename T> |
| IN void read(T &x) { |
| x = 0; char ch = getchar(); int f = 0; |
| for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar()); |
| for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar()); |
| if (f) x = ~x + 1; |
| } |
| |
| typedef long long LL; |
| const int N = 2e6 + 5; |
| int n, id[N]; |
| char str[N]; |
| LL ans; |
| |
| struct SAM { |
| int fa[N], len[N], ch[N][26], size; |
| IN SAM(){size = 1;} |
| IN void insert(int lst, int c, int now) { |
| int p = lst, np = ++size; id[now] = np; |
| len[np] = len[p] + 1; |
| for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np; |
| if (!p) fa[np] = 1; |
| else { |
| int q = ch[p][c]; |
| if (len[q] == len[p] + 1) fa[np] = q; |
| else { |
| int nq = ++size; |
| for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i]; |
| len[nq] = len[p] + 1, fa[nq] = fa[q], fa[np] = fa[q] = nq; |
| for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq; |
| } |
| } |
| ans += len[np] - len[fa[np]]; |
| } |
| }S; |
| |
| struct Trie { |
| int size = 1, tr[N][26], fa[N]; |
| IN void insert() { |
| int u = 1, m = strlen(str + 1); |
| for(int i = 1; i <= m; i++) { |
| int c = str[i] - 'a'; |
| if (!tr[u][c]) tr[u][c] = ++size; |
| fa[tr[u][c]] = u, u = tr[u][c]; |
| } |
| } |
| queue<int> Q; |
| IN void bfs() { |
| Q.push(1), id[1] = 1; |
| while (!Q.empty()) { |
| int now = Q.front(); Q.pop(); |
| for(int i = 0; i < 26; i++) |
| if (tr[now][i]) S.insert(id[now], i, tr[now][i]), Q.push(tr[now][i]); |
| } |
| } |
| }T; |
| |
| int main() { |
| read(n); |
| for(int i = 1; i <= n; i++) scanf("%s", str + 1), T.insert(); |
| T.bfs(), printf("%lld\n", ans); |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2020-10-03 【模板】AC自动机(加强版)