题目
求n个字符串两两拼接组成的n*n个字符串在文本串中出现次数
题解
和很多两个拼接的题类似
我们正反分别作出答案,然后枚举拼接位置,累加上左边乘右边
//CF1202E You Are Given Some Strings...
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct ACM{
int t[N][30],all;
int f[N],las[N],val[N];
long long res[N];
void putin(char *s)
{
int p=0;
for(int i=0;s[i];i++)
{
int now=s[i]-'a';
if(!t[p][now])t[p][now]=++all;
p=t[p][now];
}val[p]++;
}
void get_fail()
{
queue<int>q;
int p=0;
for(int i=0;i<26;i++)
if(t[p][i])q.push(t[p][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
{
p=t[u][i];
if(!p)
{
t[u][i]=t[f[u]][i];
continue;
}
q.push(p);
int pre=f[u];
while(pre&&!t[pre][i])pre=f[pre];
f[p]=t[pre][i];
las[p]=val[f[p]]?f[p]:las[f[p]];
}
}
}
void work(char *s)
{
int p=0;
for(int i=0;s[i];i++)
{
int now=s[i]-'a';
p=t[p][now];
int pre=val[p]?p:las[p];
while(pre)
{
res[i]+=val[pre];
pre=las[pre];
}
}
}
}tr1,tr2;
int n;
char st[N],s[N];
int main()
{
scanf("%s",st);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
tr1.putin(s);
reverse(s,s+strlen(s));
tr2.putin(s);
}
tr1.get_fail();
tr2.get_fail();
int len=strlen(st);tr1.work(st);
reverse(st,st+len);tr2.work(st);
long long ans=0;
for(int i=0;i<len;i++)
ans+=tr1.res[i]*tr2.res[len-i-2];
printf("%lld",ans);
}