板子题目:
n个串以及1个总串,求出n个串内在这个总串内(整串)出现的个数。
即HDU2222
AC自动机的模板题目。
AC自动机主要就是fail指针的巧妙性。。
什么是AC自动机我就不说了,网上资料也是很多的……
在这里就给出我一直在用的代码吧。
首先当然是把那n个串放入trie树了……然后匹配。。
中间AC()也就是求fail的过程值得记一记。
感觉这份代码还是挺好的。
#include<bits/stdc++.h>
using namespace std;
int n,sz,len;
int trie[1000005][26],val[1000005],fail[1000005],flag[1000005];
char ty1[55],ty2[1000005];
int Q[50005];
int find(int x,int t){
if (trie[x][t]) return trie[x][t];
if (!x) return 0;
return find(fail[x],t);
} //类似于KMP的find函数
void insert(){
int now=0;
int len=strlen(ty1);
for (int i=0;i<len;i++){
int t=ty1[i]-'a';
if (trie[now][t]) now=trie[now][t];
else now=trie[now][t]=++sz;
}
val[now]++; //在now上的单词个数val[now]
}
void AC(){ //广搜求出fail指针
int head=0,tail=1;
Q[0]=0;
while (head<tail){
int now=Q[head++];
for (int i=0;i<26;i++){
if (!trie[now][i]) continue;
int t=find(fail[now],i);
if (!now) t=0;
fail[trie[now][i]]=t;
Q[tail++]=trie[now][i];
}
}
}
void solve(){
int t=0,ans=0;
for (int i=0;i<len;i++){
int tt=ty2[i]-'a';
flag[t]=1;
t=find(t,tt);
if (flag[t]) continue;
for (int j=t;j;j=fail[j])
ans+=val[j],val[j]=0;
}
printf("%d\n",ans);
}
int main(){
int fil;
scanf("%d",&fil); //多组数据
while (fil--){
memset(val,0,sizeof(val));
memset(trie,0,sizeof(trie));
memset(fail,0,sizeof(fail));
memset(flag,0,sizeof(flag));
scanf("%d",&n);
sz=0;
for (int i=1;i<=n;i++){
scanf("%s",ty1);
insert(); //放入trie树
}
AC();
scanf("%s",ty2);
len=strlen(ty2);
solve();
}
return 0;
}