传送门
就是给两个字符串,让你求公共字串的个数。
本来大佬们都是用的广义后缀自动机,但我感觉后缀自动机已经可以做这道题了。我们对其中一个字串建出后缀自动机,然后用另外一个后缀自动机在上面统计贡献即可。
代码如下:
#include<bits/stdc++.h>
#define N 400005
#define ll long long
using namespace std;
char s[N];
int ch[N][26],n,root=1,tot[N],a[N];
ll ans=0,len[N],dp[N],siz[N];
struct suf{
int cnt,last,fa[N];
inline void insert(int c){
int p=last,newp=++cnt;
last=newp,len[newp]=len[p]+1;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=newp;
if(!p)fa[newp]=root;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[newp]=q;
else{
int newq=++cnt;
len[newq]=len[p]+1;
memcpy(ch[newq],ch[q],sizeof(ch[q]));
fa[newq]=fa[q],fa[q]=fa[newp]=newq;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=newq;
}
}
siz[newp]=1;
}
inline void build(){
scanf("%s",s+1),n=strlen(s+1),last=cnt=1;
for(int i=1;i<=n;++i)insert(s[i]-'a');
}
inline void topsort(){
for(int i=1;i<=cnt;++i)++tot[len[i]];
for(int i=1;i<=cnt;++i)tot[i]+=tot[i-1];
for(int i=1;i<=cnt;++i)a[tot[len[i]]--]=i;
for(int i=cnt;i;--i){int p=a[i];siz[fa[p]]+=siz[p];}
for(int i=2;i<=cnt;++i){
int p=a[i];
dp[p]=(len[p]-len[fa[p]])*siz[p]+dp[fa[p]];
}
}
inline void calc(){
int p=1;
ll stp=0;
for(int i=1;i<=n;++i){
int x=s[i]-'a';
for(;p&&!ch[p][x];p=fa[p]);
if(!p)stp=0,p=1;
else stp=min(stp,len[p])+1;
p=ch[p][x];
ans+=dp[fa[p]]+(stp-len[fa[p]])*siz[p];
}
}
inline void solve(){
topsort();
scanf("%s",s+1);
calc();
printf("%lld",ans);
}
}sam;
int main(){
sam.build();
sam.solve();
return 0;
}