AC自动机的入门级水题,也是我刚学完AC自动机刷的第一道水题。。。AC自动机需要先掌握字典树和KMP,具体思路比较复杂,百度文库里有个AC自动机的基础介绍推荐下http://wenku.baidu.com/link?url=jbSoDobK44Pv32EUl6u7KAo1YOfECO-_Lqr8pvmbQlMvFqnu_JTE3IqCwnKrPFLMDNQ5qGjcoS_37jo6ebxvYljQZ-6WPg38HZ2c6xVnQke
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
const int maxm=1000010;
char des[maxm],str[55];
int qin,qout,sind;
int q[maxn];
struct node{
int next[26];
int fail;
int count;
void init(){
memset(next,-1,sizeof(next));
fail=0;
count=0;
}
}s[maxn];
void insert(){
int len=strlen(str);
int i,j,ind;
for(i=ind=0;i<len;i++){
j=str[i]-'a';
if(s[ind].next[j]==-1){
s[sind].init();
s[ind].next[j]=sind++;
}
ind=s[ind].next[j];
}
s[ind].count++;
}
void fail(){
qin=qout=0;
int i,ind,indf;
for(i=0;i<26;i++){
if(s[0].next[i]!=-1){
q[qin++]=s[0].next[i];
}
}
while(qin!=qout){
ind=q[qout++];
for(i=0;i<26;i++){
if(s[ind].next[i]!=-1){
q[qin++]=s[ind].next[i];
indf=s[ind].fail;
while(indf>0&&s[indf].next[i]==-1)
indf=s[indf].fail;
if(s[indf].next[i]!=-1)
indf=s[indf].next[i];
s[s[ind].next[i]].fail=indf;
}
}
}
}
int find(){
int ct=0;
int di,i,ind,p;
int len=strlen(des);
for(di=ind=0;di<len;di++){
i=des[di]-'a';
while(ind>0&&s[ind].next[i]==-1)
ind=s[ind].fail;
if(s[ind].next[i]!=-1){
ind=s[ind].next[i];
p=ind;
while(p>0&&s[p].count!=-1){
ct+=s[p].count;
s[p].count=-1;
p=s[p].fail;
}
}
}
return ct;
}
int main(){
//freopen("2222.txt","r",stdin);
int t,n;
cin>>t;
while(t--){
scanf("%d",&n);
sind=1;
s[0].init();
for(int i=0;i<n;i++){
scanf("%s",str);
insert();
}
fail();
scanf("%s",des);
printf("%d\n",find());
}
return 0;
}