这个题有要注意的一些地方,一个是模式串可能会有重复,一个是对于每一个模式串只统计一次。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=11000;
const int maxm=1100000;
struct node
{
int next[30];
int fail,flag;
void init()
{
for (int i=0;i<30;i++)
next[i]=-1;
fail=-1;
flag=0;
}
}node[500010];
int n,m,cnt,ans;
char str[maxm];
void init()
{
cnt=0;
node[cnt++].init();
}
void insert()
{
int len=strlen(str);
int root=0;
for (int i=0;i<len;i++)
{
if (node[root].next[str[i]-'a']==-1)
{
node[cnt].init();
node[root].next[str[i]-'a']=cnt++;
}
root=node[root].next[str[i]-'a'];
}
node[root].flag++;
}
void getfail()
{
queue<int> q;
q.push(0);
while(!q.empty())
{
int root=q.front();
q.pop();
for (int i=0;i<26;i++)
if (node[root].next[i]!=-1)
{
int now=node[root].next[i];
int tmp=node[root].fail;
while (tmp!=-1&&node[tmp].next[i]==-1)
tmp=node[tmp].fail;
if (node[tmp].next[i]!=-1)
{
node[now].fail=node[tmp].next[i];
//node[now].flag+=node[node[now].fail].flag;
}
else node[now].fail=0;
q.push(now);
}
else//我个人来讲,比较喜欢把所有next填满,这样应该也会更快。
if (root!=0)
{
node[root].next[i]=node[node[root].fail].next[i];
}
else node[root].next[i]=0;
}
}
void getans()
{
int len=strlen(str);
int root=0;
for (int i=0;i<len;i++)
{
int now=node[root].next[str[i]-'a'];
int tmp=node[root].fail;
while (tmp!=-1)
{
ans+=node[node[tmp].next[str[i]-'a']].flag;
node[node[tmp].next[str[i]-'a']].flag=0;
tmp=node[tmp].fail;
}
root=now;
ans+=node[root].flag;
node[root].flag=0;
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
init();
for (int i=0;i<n;i++)
{
scanf("%s",str);
insert();
}
getfail();
scanf("%s",str);
ans=0;
getans();
cout<<ans<<endl;
}
return 0;
}