第一道AC自動機題~ 其實就是字典樹上的KMP演算法,主要就是學會建字典樹和構造失敗指標。字典樹我用的是數組類比的方法~
AC代碼:
#include <iostream>#include<string.h>#include<algorithm>#include<cstdio>#include<queue>#define Fp freopen("1.txt","r",stdin)#define N 2000005using namespace std;void in(int &a){ char ch; while((ch=getchar())<'0'||ch>'9'); for( a=0;ch>='0'&&ch<='9';ch=getchar()) a=a*10+ch-'0';}typedef struct node{int next[26];int num;int fail;void init(){memset(next,-1,sizeof(next));num=0;fail=-1;}}Node;Node s[N];int p;char a[1000000];void insert(){int ind=0;for(int i=0;a[i];++i){int x=a[i]-'a';if(s[ind].next[x]==-1) { s[++p].init(); s[ind].next[x]=p; }ind=s[ind].next[x];}++s[ind].num;}void AC(){queue<int>Q;int root=0;s[root].fail=-1;Q.push(root);while(!Q.empty()){int t=Q.front();Q.pop();for(int i=0;i<26;++i){int ind=s[t].next[i];if(ind!=-1){if(t==root) s[ind].fail=root;else{ int p=s[t].fail; while(p!=-1) { if(s[p].next[i]!=-1) { s[ind].fail=s[p].next[i]; break; } p=s[p].fail; } if(p==-1) s[ind].fail=root; }Q.push(ind);} }}}int Find(){ int root=0; int ct=0; int res=root; for(int i=0;a[i];++i) { int x=a[i]-'a'; while(res!=root&&s[res].next[x]==-1) res=s[res].fail; res=s[res].next[x]; if(res==-1) res=root; int ans=res; while(ans!=root&&s[ans].num>0) { ct+=s[ans].num; s[ans].num=-1; ans=s[ans].fail; } } return ct;}int main(){ Fp; int T; in(T); while(T--) { s[0].init(); int n; //scanf("%d",&n); in(n); //gets(a); while(n--) { gets(a); insert(); } gets(a); AC(); printf("%d\n",Find()); }return 0;}
參考:
http://blog.csdn.net/niushuai666/article/details/7002823
http://www.cnblogs.com/zhuangli/archive/2008/08/13/1267249.html