因为我太菜了,我写了LCS就忘了(温故而知新的重要性啊)
和LCS代码几乎一样
又一个算贡献的问题
now->pre的贡献为siz*(now->step-pre->step)
这个时候可以预处理
但是当前匹配串长度并不一定是now->step
这很重要
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int INT;
#define LL long long
const int N=1e6+100;
char S[N];
struct SAM{
struct Node{
int vis[26];
int pre;
int step;
}SA[N];
int cnt,last;
int siz[N];
int C[N];
int A[N];
LL F[N];
LL ans;
inline void Insert(char C){
int p=last;
int np=++cnt;
last=np;
SA[np].step=SA[p].step+1;
for(;!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;
}
}
siz[np]++;
}
void Getans(int p,int len){
if(SA[p].pre){
ans+=(LL)siz[p]*(LL)(len-SA[SA[p].pre].step);
Getans(SA[p].pre,SA[SA[p].pre].step);
}
}
void Solve(){
cnt=last=1;
scanf("%s",S+1);
int len=strlen(S+1);
for(int i=1;i<=len;i++)Insert(S[i]);//puts("hh");
for(int i=1;i<=cnt;i++)C[SA[i].step]++;
for(int i=1;i<=len;i++)C[i]+=C[i-1];
for(int i=1;i<=cnt;i++)A[C[SA[i].step]--]=i;
for(int i=cnt;i>=1;i--){
int p=SA[A[i]].pre;
siz[p]+=siz[A[i]];
}
for(int i=1;i<=cnt;i++){
F[A[i]]=F[SA[A[i]].pre]+siz[A[i]]*(SA[A[i]].step-SA[SA[A[i]].pre].step);
}
scanf("%s",S+1);
len=strlen(S+1);
int now=1;
int LCS=0;
for(int i=1;i<=len;i++){
if(SA[now].vis[S[i]-'a']){
now=SA[now].vis[S[i]-'a'];
LCS++;
}
else{
for(;now&&!SA[now].vis[S[i]-'a'];now=SA[now].pre);
if(!now)now=1,LCS=0;
else{
LCS=SA[now].step+1;
now=SA[now].vis[S[i]-'a'];
}
}
ans+=F[SA[now].pre]+siz[now]*(LCS-SA[SA[now].pre].step);
}
cout<<ans;
}
}Solution;
INT main(){
// freopen("2841.in","r",stdin);
Solution.Solve();
}