AC自動機有很多版本,但是上一個版本的話找字典樹結點的兒子要for,暴力去for,這個很費時間,所有我們可以加map去優化。
#include<map> #include<queue> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define Maxchar 1000000 #define Maxm 10000 #define Maxn 50 #define Maxs 26 #define mes(x,y) memset(x,y,sizeof(x)); #define mpy(x,y) memcpy(x,y,sizeof(x)) #define INF 2147483647 using namespace std; struct Tire{ int s,c[Maxs+1],fail; void clear(){ s=fail=0;mes(c,-1); } }t[Maxn*Maxm+1]; int T,tot,ans,n; char a[Maxchar+1]; map<int, map<int,int> >qt; void bt(int root){ int x=root,len=strlen(a+1); for(int i=1;i<=len;i++){ int y=a[i]-'a'+1; if(t[x].c[y]==-1){ qt[x][++qt[x][0]]=y; t[x].c[y]=++tot; t[tot].clear(); } x=t[x].c[y]; } t[x].s++; } queue<int> q; void bfs(){ int x,y,son; q.push(0); while(q.empty()==0){ int x=q.front(); for(int i=1;i<=qt[x][0];i++){ y=qt[x][i]; son=t[x].c[y]; if(x==0)t[son].fail=0; else{ int j=t[x].fail; while(j!=0&&t[j].c[y]==-1)j=t[j].fail; t[son].fail=max(t[j].c[y],0); } q.push(son); } q.pop(); } } void solve(){ int x=0,len=strlen(a+1),j; for(int i=1;i<=len;i++){ int y=a[i]-'a'+1; while(x!=0&&t[x].c[y]==-1)x=t[x].fail; x=t[x].c[y]; if(x==-1){x=0;continue;} j=x; while(t[j].s!=0){ ans+=t[j].s; t[j].s=0; j=t[j].fail; } } printf("%d\n",ans); } int main(){ scanf("%d",&T); while(T--){ ans=tot=0; scanf("%d",&n); t[0].clear(); qt.clear(); for(int i=1;i<=n;i++){ scanf("%s",a+1); bt(0); } bfs(); scanf("%s",a+1); solve(); } return 0; }
查看原文:http://hz2016.tk/blog/?p=31