求本质不同的字符串个数
两种方法:
1)求right集合大小,暨parent树上一个点子树的大小,这是一个递推式,并不是指点的个数
2)由step函数求因为now->step - pre->step 表示一条边的贡献,所以全部加起来就好了
本题使用法2
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e6+1000;
char S[N];
struct SAM{
struct Node{
int vis[26];
int pre;
int step;
}SA[N];
int cnt,last;
inline void Insert(char C){
int p=last;
int np=++cnt;
last=np;
SA[np].step=SA[p].step+1;
for(;p&&!SA[p].vis[C-'a'];p=SA[p].pre)SA[p].vis[C-'a']=np;
if(!p){
SA[np].pre=1;
}
else{
int q=SA[p].vis[C-'a'];
if(SA[q].step==SA[p].step+1){
SA[np].pre=q;
}
else{
int nq=++cnt;
SA[nq].step=SA[p].step+1;
memcpy(SA[nq].vis,SA[q].vis,sizeof(SA[q].vis));
SA[nq].pre=SA[q].pre;
SA[np].pre=SA[q].pre=nq;
for(;SA[p].vis[C-'a']==q;p=SA[p].pre)SA[p].vis[C-'a']=nq;
}
}
}
void Solve(){
scanf("%s",S+1);
int len=strlen(S+1);
cnt=last=1;
for(int i=1;i<=len;i++){
Insert(S[i]);
}
long long ans=0;
for(int i=2;i<=cnt;i++){
ans+=SA[i].step-SA[SA[i].pre].step;
}
cout<<ans;
}
}Solution;
int main(){
// freopen("hihocoder1445.in","r",stdin);
Solution.Solve();
}