【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6096
【题目大意】
给出一些字符串,给出前缀后缀模式询问,问有多少字符串符合该模式
【题解】
我们将字符串变为双倍,在中间增加拼接符,
对于每个前后缀模式,我们将其处理为[后缀+拼接符+前缀]的形式,
那么原题等价于统计前后缀模式在多少个字符串中出现,
我们用所有的前后缀模式建立AC自动机,用每个字符串在AC自动机上跑匹配,
最后统计fail链前继累加和即可。
对于前缀和后缀不能重叠的条件,
我们记录串长+1作为其搜索长度,比如abcde#abcde我们用长度为6来记录,
这样子就不会出现匹配到cde#abc这样子的情况了
【代码】
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1200010;
namespace AC_DFA{
const int Csize=27;
int tot,son[N][Csize],sum[N],fail[N],q[N],ans[N],dph[N],match[N];
void Initialize(){
memset(sum,0,sizeof(int)*(tot+1));
memset(dph,0,sizeof(int)*(tot+1));
memset(ans,0,sizeof(int)*(tot+1));
memset(match,0,sizeof(int)*(tot+1));
memset(fail,0,sizeof(int)*(tot+1));
for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0;
tot=0; fail[0]=-1;
}
inline int Tr(char ch){return ch-'a';}
int Insert(char *s){
int x=0;
for(int l=strlen(s),i=0,w;i<l;i++){
if(!son[x][w=Tr(s[i])]){
son[x][w]=++tot;
dph[tot]=i+1;
}x=son[x][w];
}sum[x]++;
return x;
}
void MakeFail(){
int h=1,t=0,i,j,x;
for(i=0;i<Csize;i++)if(son[0][i])q[++t]=son[0][i];
while(h<=t)for(x=q[h++],i=0;i<Csize;i++)
if(son[x][i]){
fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i];
match[son[x][i]]=sum[son[x][i]]?son[x][i]:match[fail[son[x][i]]];
}else son[x][i]=son[fail[x]][i];
}
void Search(char *s,int len){
for(int l=strlen(s),i=0,x=0,w;i<l;i++){
x=son[x][Tr(s[i])];
while(dph[x]>len)x=fail[x];
ans[match[x]]++;
}
}
int d[N],st[N];
void Solve(){
int k=0;
memset(d,0,sizeof(int)*(tot+1));
for(int i=1;i<=tot;i++)d[fail[i]]++;
for(int i=1;i<=tot;i++)if(!d[i])st[k++]=i;
for(int i=0;i<k;i++){
int j=fail[st[i]];
ans[j]+=ans[st[i]];
if(!--d[j])st[k++]=j;
}
}
}
int len[100010],pos[100010];
char ss[N],t1[N],t2[N];
char *s[100010];
using namespace AC_DFA;
int main(){
int T,n,q;
scanf("%d",&T);
while(T--){
Initialize();
scanf("%d%d",&n,&q);
for(int i=0,j=0;i<n;i++){
s[i]=ss+j;
scanf("%s",s[i]);
len[i]=strlen(s[i])+1;
j+=len[i];
strcpy(ss+j,s[i]);
ss[j-1]='z'+1;
j+=len[i];
}
for(int i=0;i<q;i++){
t1[0]='z'+1;
scanf("%s%s",t1+1,t2);
strcat(t2,t1);
pos[i]=Insert(t2);
}MakeFail();
for(int i=0;i<n;i++)Search(s[i],len[i]);
Solve();
for(int i=0;i<q;i++)printf("%d
",ans[pos[i]]);
}return 0;
}