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