P4081 [USACO17DEC]Standing Out from the Herd P [广义SAM]
我们直接把重复的部分去掉。
\(\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;
}