您的位置:首页 > 其它

模板 AC自动机

2017-07-20 21:31 295 查看
板子题目:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: