广义 S A M SAM SAM离线
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6+10;
int n;
char a[maxn];
struct Tire
{
int id,fa[maxn],col[maxn],zi[maxn][27];
Tire() { id = 1; }
inline void insert(char a[] )
{
int len = strlen( a+1 ), p = 1;
for(int i=1;i<=len;i++)
{
int c = a[i]-'a';
if( !zi[p][c] ) zi[p][c] = ++id,fa[id] = p, col[id] = c;
p = zi[p][c];
}
}
}T;
struct extend_SAM
{
int id,pos[maxn],fa[maxn],len[maxn],zi[maxn][27]; queue<int>q;
extend_SAM(){ id = 1; }//初始化根节点为1
int insert(int c,int las)
{
int p = las, np = ++id;
len[np] = len[p]+1;
for( ; p && zi[p][c]==0;p=fa[p] ) zi[p][c] = np;
if( p==0 ) fa[np] = 1;
else
{
int q = zi[p][c];
if( len[q]==len[p]+1 ) fa[np] = q;
else
{
int nq = ++id;
len[nq] = len[p]+1, fa[nq] = fa[q];
memcpy( zi[nq],zi[q],sizeof zi[nq] );
fa[q] = fa[np] = nq;
for( ; p && zi[p][c]==q;p=fa[p] ) zi[p][c] = nq;
}
}
return np;
}
void build()
{
for(int i=0;i<=25;i++) if( T.zi[1][i] ) q.push( T.zi[1][i] );
pos[1] = 1;
while( !q.empty() )
{
int u = q.front(); q.pop();
pos[u] = insert( T.col[u],pos[T.fa[u]] );
for(int i=0;i<=25;i++) if( T.zi[u][i] ) q.push( T.zi[u][i] );
}
}
void solve()
{
long long ans = 0;
for(int i=2;i<=id;i++) ans += len[i]-len[fa[i]];
printf("%lld",ans);
}
}sam;
int main()
{
cin >> n;
for(int i=1;i<=n;i++) scanf("%s",a+1),T.insert( a );
sam.build(); sam.solve();
}
在线
int zi[maxn][12],fa[maxn],l[maxn],las=1,id=1;
void insert(int p,int c)
{
if( zi[p][c] )
{
int q = zi[p][c];
if( l[q]==l[p]+1 ) las = q;//完全吻合的节点
else
{
int nq = ++id; las = nq;
memcpy( zi[nq],zi[q],sizeof zi[nq] );
fa[nq] = fa[q], l[nq] = l[p]+1;
fa[q] = nq;
for( ; p&&zi[p][c]==q;p=fa[p] ) zi[p][c] = nq;
}
}
else
{
int np = ++id; las = np;
l[np] = l[p]+1;
for( ; p&&zi[p][c]==0 ; p = fa[p] ) zi[p][c] = np;
if( !p ) fa[np] = 1;
else
{
int q = zi[p][c];
if( l[q]==l[p]+1 ) fa[np] = q;
else
{
int nq = ++id;
memcpy( zi[nq],zi[q],sizeof zi[nq] );
fa[nq] = fa[q], l[nq] = l[p]+1;
fa[np] = fa[q] = nq;
for( ; p&&zi[p][c]==q;p=fa[p] ) zi[p][c] = nq;
}
}
}
}