题目描述
题目大意
给出母串T和若干子串S,定义f(x,y)表示字符串y在x中出现次数
求∑∑f(T,Si+Sj)
题解
当初被D降智后没发现这是到SB题
枚举连接位置,ans=∑以i为结尾的个数*以i+1为开头的个数
AC自动机随便搞
时间:O(n)
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;
int tr[200002][26];
int sum[200002];
int fa[200002];
int S[200002];
int T[200002];
int b[200002];
int d[200002];
long long s1[200002];
long long s2[200002];
int N,n,m,i,j,k,l,len,h,t;
long long ans;
char ch;
void New(int t,int x)
{
if (!tr[t][x])
tr[t][x]=++len;
}
int main()
{
// freopen("CF1202E.in","r",stdin);
// freopen("a.in","r",stdin);
ch=getchar();
while (ch>='a' && ch<='z')
{
S[++N]=ch-'a';
ch=getchar();
}
scanf("%d",&n);
fo(i,1,n)
{
while (ch<'a' || ch>'z')
ch=getchar();
while (ch>='a' && ch<='z')
{
T[++m]=ch-'a';
ch=getchar();
}
b[i]=m;
}
len=1;
fo(i,1,n)
{
k=1;
fo(j,b[i-1]+1,b[i])
{
New(k,T[j]);
k=tr[k][T[j]];
}
++sum[k];
}
h=0;
t=1;
d[1]=1;
while (h<t)
{
++h;
fo(i,0,25)
if (tr[d[h]][i])
{
j=fa[d[h]];
while (j && !tr[j][i])
j=fa[j];
if (!j)
fa[tr[d[h]][i]]=1;
else
fa[tr[d[h]][i]]=tr[j][i];
d[++t]=tr[d[h]][i];
sum[tr[d[h]][i]]+=sum[fa[tr[d[h]][i]]];
}
}
k=1;
fo(i,1,N)
{
while (k && !tr[k][S[i]])
k=fa[k];
if (!k)
k=1;
else
k=tr[k][S[i]];
s1[i]=sum[k];
}
// ---
memset(sum,0,sizeof(sum));
memset(fa,0,sizeof(fa));
memset(tr,0,sizeof(tr));
len=1;
fo(i,1,n)
{
k=1;
fd(j,b[i],b[i-1]+1)
{
New(k,T[j]);
k=tr[k][T[j]];
}
++sum[k];
}
h=0;
t=1;
d[1]=1;
while (h<t)
{
++h;
fo(i,0,25)
if (tr[d[h]][i])
{
j=fa[d[h]];
while (j && !tr[j][i])
j=fa[j];
if (!j)
fa[tr[d[h]][i]]=1;
else
fa[tr[d[h]][i]]=tr[j][i];
d[++t]=tr[d[h]][i];
sum[tr[d[h]][i]]+=sum[fa[tr[d[h]][i]]];
}
}
k=1;
fd(i,N,1)
{
while (k && !tr[k][S[i]])
k=fa[k];
if (!k)
k=1;
else
k=tr[k][S[i]];
s2[i]=sum[k];
}
// ---
fo(i,1,N-1)
ans+=s1[i]*s2[i+1];
printf("%I64d\n",ans);
}