AC自动机模板题,给你n个模式串和一个文本串,问你有几个模式串在文本串出现过。
注意防止重复统计
这里推荐一波郭大爷的介绍,简单易懂。
http://www.bilibili.com/video/av6295004/
这个视频里的hdu2222代码好像有点问题,我现在这份代码已经更改。
#include<cstdio> #include<cstring> #include<queue> using namespace std; queue<int>q; int child[500010][26],fail[500010],cnts[500010],size; void Insert(char S[]) { int len=strlen(S); int now=0; for(int i=0;i<len;++i) { if(!child[now][S[i]-'a']) child[now][S[i]-'a']=size++; now=child[now][S[i]-'a']; } if(cnts[now]==-1) cnts[now]=0; ++cnts[now]; } void build() { fail[0]=-1; q.push(0); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=0;i<26;++i) if(child[U][i]) { int V=fail[U]; while(V!=-1) { if(child[V][i]) { fail[child[U][i]]=child[V][i]; break; } V=fail[V]; } if(V==-1) fail[child[U][i]]=0; if(cnts[fail[child[U][i]]]!=-1 && cnts[child[U][i]]==-1) cnts[child[U][i]]=0; q.push(child[U][i]); } } } int calc(int U)//˳×ÅfailÖ¸Õë»ØÈ¥£¬¿´Í³¼Æµ½Á˼¸¸ö´® { int res=0; while(U) { if(cnts[U]==-1) break; res+=cnts[U]; cnts[U]=-1;//·ÀÖ¹Öظ´Í³¼Æ U=fail[U]; } return res; } int match(char S[]) { int len=strlen(S); int res=0,now=0; for(int i=0;i<len;++i) { if(child[now][S[i]-'a']) now=child[now][S[i]-'a']; else { int U=fail[now]; while(U!=-1 && child[U][S[i]-'a']==0) U=fail[U]; if(U==-1) now=0; else now=child[U][S[i]-'a']; } if(cnts[now]!=-1) res+=calc(now); } return res; } void Init() { memset(child,0,sizeof(child)); memset(fail,0,sizeof(fail)); memset(cnts,-1,sizeof(cnts)); size=1; } int T,n; char s[1000010]; int main() { //freopen("hdu2222.in","r",stdin); scanf("%d",&T); for(;T;--T) { Init(); scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",s); Insert(s); } build(); scanf("%s",s); printf("%d ",match(s)); } return 0; }