AC自动机
2016-07-29 09:22
155 查看
#include<iostream> #include<string.h> #include<stdio.h> #include<queue> using namespace std; int child[240000][26],tot; int fail[240000],num[240000]; char txt[1000002],s[51]; void ac_insert() //trie树的建立 { int now=1,i,x,l=strlen(s); for(i=0;i<l;i++) { x=s[i]-'a'; if(!child[now][x]) { child[now][x]=++tot; memset(child[tot],0,sizeof(child[tot])); } now=child[now][x]; } num[now]++; } void ac_fail() //fail数组, { queue<int> q; int i,fa,p,son; for(i=0;i<26;i++) if(child[1][i]) { fail[child[1][i]]=1; //根节点直接连接的点的fail指向根节点(now=1) q.push(child[1][i]); } fail[1]=0; //根节点的fail为0 while(!q.empty()) { fa=q.front(),q.pop(); for(i=0;i<26;i++) { son=child[fa][i]; if(son) { p=fail[fa]; //其他节点沿着它父亲的fail直到找到一个相同字母的 while(p) { if(child[p][i]) { fail[son]=child[p][i]; break; } p=fail[p]; } if(!p) fail[son]=1; //如果没找到,fail就指向根节点 q.push(son); } } } } void query() { int i,x,temp,now=1,cnt=0,l=strlen(txt); for(i=0;i<l;i++) { x=txt[i]-'a'; while(!child[now][x]&&now!=1) now=fail[now]; //沿着fail一直找,直到到了根节点或者找到了 now=child[now][x]; if(!now) now=1; temp=now;//temp用来防止遗漏,新的字母增加进来之后,一直找最长后缀来寻找是否有这样的单词。 while(temp!=1) { if(num[temp]>=0) { cnt+=num[temp]; num[temp]=-1; } else break; temp=fail[temp]; } } printf("%d\n",cnt); } int main() { int t,n; scanf("%d",&t); while(t--) { memset(child[1],0,sizeof(child[1])); memset(num,0,sizeof(num)); scanf("%d",&n); tot=1; while(n--) { scanf("%s",s); ac_insert(); } memset(fail,0,(tot+1)*sizeof(int)); ac_fail(); scanf("%s",txt); query(); } }
#include<iostream> #include<string.h> #include<stdio.h> #include<queue> using namespace std; int child[240000][26],tot; int fail[240000],num[240000]; char txt[1000002],s[51]; void ac_insert() //trie树的建立 { int now=1,i,x,l=strlen(s); for(i=0;i<l;i++) { x=s[i]-'a'; if(!child[now][x]) { child[now][x]=++tot; memset(child[tot],0,sizeof(child[tot])); } now=child[now][x]; } num[now]++; } void ac_fail() //fail数组, { queue<int> q; int i,fa,son; for(i=0;i<26;i++) if(child[1][i]) { fail[child[1][i]]=1; //根节点直接连接的点的fail指向根节点(now=1) q.push(child[1][i]); } else child[1][i]=1; fail[1]=0; //根节点的fail为0 while(!q.empty()) { fa=q.front(),q.pop(); for(i=0;i<26;i++) { son=child[fa][i]; if(son) { fail[son]=child[fail[fa]][i]; q.push(son); } else child[fa][i]=child[fail[fa]][i]; } } } void query() { int i,temp,now=1,cnt=0,l=strlen(txt); for(i=0;i<l;i++) { now=child[now][txt[i]-'a']; temp=now;//temp用来防止遗漏,新的字母增加进来之后,一直找最长后缀来寻找是否有这样的单词。 while(temp!=1) { if(num[temp]>=0) { cnt+=num[temp]; num[temp]=-1; } else break; temp=fail[temp]; } } printf("%d\n",cnt); } int main() { int t,n; scanf("%d",&t); while(t--) { memset(child[1],0,sizeof(child[1])); memset(num,0,sizeof(num)); scanf("%d",&n); getchar(); tot=1; while(n--) { gets(s); ac_insert(); } memset(fail,0,(tot+1)*sizeof(int)); ac_fail(); gets(txt); query(); } }
相关文章推荐
- AC 自动机 HDU 2896
- bzoj 1212: [HNOI2004]L语言(AC自动机+DP)
- 【POJ3691】 DNA repair (AC自动机+DP)
- AC自动机——病毒侵袭 ( HDU 2896 )
- POJ 2778 DNA Sequence (AC 自动机+矩阵)
- 关键词匹配(Ac自动机模板题)
- HDU 2222 Keywords Search (AC自动机)
- hdu_3341_Lost's revenge(AC自动机+状态hashDP)
- AC自动机的两个模板
- 【hdu 3065】病毒侵袭持续中(AC自动机)
- 字符串(AC自动机):HDU 5129 Yong Zheng's Death
- Vijos P1951 玄武密码 (AC自动机)
- UVA 1078 Password Suspects(AC自动机+dp)
- AC自动机+高斯消元求解线性方程--2016icpc沈阳H
- AC自动机——Uva 11468 子串
- UVA 11019 Matrix Matcher(AC自动机)
- AC自动机匹配
- AC自动机...
- HDU 3065 病毒侵袭持续中(AC自动机)
- hdu 2222 Keywords Search(AC自动机入门题)