有多大的思想,才有多大的能量。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#define N 500010
using namespace std;
int trie[N][27],f[N],last[N],val[N],n,cnt,ans;
char T[2*N],P[55];
void make(int x) //求答案,与刘汝佳的print()相似
{
if(!x)return;
if(val[x]) ans+=val[x],val[x]=0;
make(last[x]);
}
void add_trie(char *P) //模板串加入Trie树
{
int x=0,i=0;char ch;
while(P[i])
{
ch=P[i]-‘a‘;
if(!trie[x][ch])trie[x][ch]=++cnt;
x=trie[x][ch]; i++;
}
val[x]++; //有重复模板串
}
void getfail() //bfs求fail[](and last[])
{
queue<int> q; int rt,u,v;
for(int i=0;i<26;i++)
if(trie[0][i]) q.push(trie[0][i]),f[trie[0][i]]=last[trie[0][i]]=0;
while(!q.empty())
{
rt=q.front(); q.pop();
for(int i=0;i<26;i++)
{
u=trie[rt][i];
if(!u)continue; q.push(u);v=f[rt];
while(v&&!trie[v][i])v=f[v];
f[u]=trie[v][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void Aho_Corasick_automaton(char *T) //匹配
{
int x=0,ch;
for(int i=0;T[i];i++)
{
ch=T[i]-‘a‘;
while(x&&!trie[x][ch])x=f[x];
x=trie[x][ch];
if(val[x]) make(x);
else if(last[x]) make(last[x]);
}
}
int main()
{
int cas;scanf("%d",&cas);while(cas--)
{
memset(trie,0,sizeof(trie));
memset(val,0,sizeof(val));
scanf("%d",&n); ans=0;cnt=0;
for(int i=1;i<=n;i++) scanf("%s",P), add_trie(P);
getfail();
scanf("%s",T);
Aho_Corasick_automaton(T);
printf("%d\n",ans);
}
return 0;
}
/* 对于多组数据 :
trie[],val[] 必须memset
f[],last[] 不必memset,
因为(在bfs求fail值时)每个点的f和last值来源于之前的点
所以只需在往队列里加初值时,把对应的点的f和last赋值为0就行了 */
void getfail()
{
queue<int> q; int rt,u,v;
for(int i=0;i<26;i++)
if(trie[0][i]) q.push(trie[0][i]),f[trie[0][i]]=last[trie[0][i]]=0;
while(!q.empty())
{
rt=q.front(); q.pop();
for(int i=0;i<26;i++)
{
u=trie[rt][i];
if(!u){trie[rt][i]=trie[f[rt]][i];continue;}; //**
q.push(u);v=f[rt];
f[u]=trie[v][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void Aho_Corasick_automaton(char *T)
{
int x=0,ch;
for(int i=0;T[i];i++)
{
ch=T[i]-‘a‘;
x=trie[x][ch];
if(val[x]) make(x); //**
else if(last[x]) make(last[x]);
}
}原文:http://www.cnblogs.com/zj75211/p/6632111.html