解题思路:AC自动机模板题,没什么好说的。关于题目中一些要注意的问题详见代码注释,代码复杂度为O(n),n为字符串长度
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=500009;
struct node
{
char c;
int next[26],fg,fail;
}s[MAXN];
int cnt,ans;
char tp[60],t[1000009];
queue<int> q;
void make_tire()//建立字典树
{
int l=strlen(tp);
int r=0;
for(int i=0;i<l;i++)
{
if(s[r].next[tp[i]-'a']==-1)
{
s[cnt].c=tp[i];
s[cnt].fg=0;
s[cnt].fail=-1;
memset(s[cnt].next,-1,sizeof(s[cnt].next));
s[r].next[tp[i]-'a']=cnt++;
}
r=s[r].next[tp[i]-'a'];
}
s[r].fg++;
}
void make_ac()//建立ac自动机
{
int a,p,r;
q.push(0);
while(!q.empty())
{
r=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(s[r].next[i]==-1) continue;
a=s[r].next[i];
q.push(a);
p=s[r].fail;
while(p!=-1)
{
if(s[p].next[i]!=-1)
{
s[a].fail=s[p].next[i];
break;
}
p=s[p].fail;
}
if(p==-1)
{
s[a].fail=0;
}
}
}
}
void query()
{
int l=strlen(t),temp;
int r=0,v,f;
for(int i=0;i<l;i++)
{
v=t[i]-'a';
if(s[r].next[v]!=-1)
{
r=s[r].next[v];
}else
{
f=s[r].fail;
while(f!=-1)
{
if(s[f].next[v]!=-1)
{
r=s[f].next[v];
break;
}
f=s[f].fail;
}
if(f==-1) r=0;
}
temp=r;
while(temp!=0)//这是防止出现一个问题,比如she,和he,对于she来说,没有这部,只会统计she,不会统计he
{
if(s[temp].fg>=0)
{
ans+=s[temp].fg;
s[temp].fg=-1;//表示这个关键字已经访问过了,已经纳入统计,以后无需再访问。没有会超时的!!!!
}else
break;
temp=s[temp].fail;
}
}
}
int main()
{
//freopen("t.txt","r",stdin);
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(s[0].next,-1,sizeof(s[0].next));
s[0].fg=0;
s[0].fail=-1;
cnt=1;
getchar();
for(int i=0;i<n;i++)
{
gets(tp);
//printf("%s\n",tp);
make_tire();
}
while(!q.empty()) q.pop();
make_ac();
gets(t);
ans=0;
query();
printf("%d\n",ans);
}
return 0;
}