原题:http://acm.hdu.edu.cn/showproblem.php?pid=2222
题解:AC自动机的本质是将模式串建成字典树跑kmp。首先新建字典树,bfs预处理失败指针,查找就可以。
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=5e5+5;
int trie[N][26];
int mark[N],nxt[N],tot,cas,n;
char s[1000010];
queue<int> q;
inline void ins(char *s){//建字典树
int len=strlen(s+1);
int p=1;
for(int i=1,c;i<=len;i++){
c=s[i]-'a';
if(!trie[p][c]) {
trie[p][c]=++tot;memset(trie[tot],0,sizeof trie[tot]);
}
p=trie[p][c];
}
mark[p]++;
}
void bfs(){
//fail指针
for(int i=0;i<26;i++) trie[0][i]=1;
q.push(1);nxt[1]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
if(!trie[u][i]) trie[u][i]=trie[ nxt[u] ][i]; //小优化
else {
q.push(trie[u][i]);
int v=nxt[u];
while(v>0 && !trie[v][i]) v=nxt[v];
nxt[trie[u][i]]=trie[v][i];
}
}
}
}
int query(char *s){
int len=strlen(s+1);
int p=1;int ans=0;
for(int i=1,c,k;i<=len;i++){
c=s[i]-'a';
k=trie[p][c];
while(k>1){
ans+=mark[k];mark[k]=0;
k=nxt[k];
}
p=trie[p][c];
}
return ans;
}
int main(){
// freopen("hdu2222.in","r",stdin);
scanf("%d",&cas);
while(cas--){
memset(mark,0,sizeof mark);
for(int i=0;i<26;i++) trie[0][i]=1,trie[1][i]=0;
tot=1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s+1);ins(s);
}
bfs();
scanf("%s",s+1);
printf("%d\n",query(s));
}
return 0;
}