建立广义后缀自动机,维护两个串的size
那么答案等于∑(leni−lenfai)×size0×size1
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200005;
char str1[N],str2[N];
int n1,n2,S,last,cnt;
long long ans;
int fa[N<<2],len[N<<2],ch[N<<2][26],size[2][N<<2],cc[N<<2],q[N<<2];
inline void extend(char c)
{
int p=last,np=++cnt; last=np;
len[np]=len[p]+1;
while (p&&!ch[p][c]) ch[p][c]=np,p=fa[p];
if (!p) fa[np]=S;
else
{
int q=ch[p][c];
if (len[p]+1==len[q]) fa[np]=q;
else
{
int nq=++cnt;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
len[nq]=len[p]+1;
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while (ch[p][c]==q) ch[p][c]=nq,p=fa[p];
}
}
}
int main()
{
scanf("%s",str1);
scanf("%s",str2);
n1=strlen(str1);
n2=strlen(str2);
S=last=++cnt;
int p=S;
for (int i=0;i<n1;i++)
{
extend(str1[i]-'a');
p=ch[p][str1[i]-'a'];
size[0][p]++;
}
last=S;
p=S;
for (int i=0;i<n2;i++)
{
extend(str2[i]-'a');
p=ch[p][str2[i]-'a'];
size[1][p]++;
}
for (int i=1;i<=cnt;i++) ++cc[len[i]];
for (int i=1;i<=cnt;i++) cc[i]+=cc[i-1];
for (int i=1;i<=cnt;i++) q[cc[len[i]]--]=i;
for (int i=cnt;i;i--) size[0][fa[q[i]]]+=size[0][q[i]],size[1][fa[q[i]]]+=size[1][q[i]];
for (int i=1;i<=cnt;i++)
ans+=(long long)(len[i]-len[fa[i]])*size[0][i]*size[1][i];
cout << ans << endl;
return 0;
}