我们直接把重复的部分去掉。
\(\sum len_i - len_{fa_i}\)
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 62; char s[maxn], str[maxn]; int tot = 0 ; long long Ans[maxn] ; struct SAM { int ch[maxn][26], cnt, len[maxn], fa[maxn]; SAM() { cnt = 1; } int ins(int c, int las) { int p = las, np = ++cnt; 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 = ++cnt; memcpy(ch[nq], ch[q], sizeof(ch[q])); fa[nq] = fa[q], fa[q] = fa[np] = nq, len[nq] = len[p] + 1; for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq; } } return np; } int id[maxn] ; void col(int x , int c) { for( ; x && id[x] ^ c && ~ id[x] ; x = fa[x]) id[x] = (id[x]) ? -1 : c ; } void calc() { int c = 1 , p = 1 ; for(int i = 1 ; i <= tot ; i ++) { if(! isspace(str[i])) { col(p = ch[p][str[i] - 'a'] , c) ; } else { p = 1 , ++ c ; } } for(int i = 1 ; i <= cnt ; i ++) { if(~ id[i]) { Ans[id[i]] += len[i] - len[fa[i]] ; } } } } sam; struct Trie { int ch[maxn][26], cnt, qwq[maxn], fa[maxn]; Trie() { cnt = 1; } void ins(int len) { int p = 1; for (int i = 1; i <= len; i++) { int c = s[i] - 'a'; if (!ch[p][c]) ch[p][c] = ++cnt, qwq[cnt] = c, fa[cnt] = p; p = ch[p][c]; } } int pos[maxn]; void buildsam() { queue<int> q; for (int i = 0; i < 26; i++) if (ch[1][i]) q.push(ch[1][i]); pos[1] = 1; while (!q.empty()) { int u = q.front(); q.pop(); pos[u] = sam.ins(qwq[u], pos[fa[u]]); for (int i = 0; i < 26; i++) if (ch[u][i]) q.push(ch[u][i]); } } } trie; void cpy(int len) { for(int i = 1 ; i <= len ; i ++) str[++ tot] = s[i] ; str[++ tot] = '\n' ; } int main() { int _; scanf("%d", &_); for(int i = 1 ; i <= _ ; i ++) scanf("%s", s + 1), trie.ins(strlen(s + 1)), cpy(strlen(s + 1)); trie.buildsam(), sam.calc(); for(int i = 1 ; i <= _ ; i ++) printf("%lld\n" , Ans[i]) ; return 0; }
来源:https://www.cnblogs.com/Isaunoya/p/12568935.html