病毒侵袭持续中 HDU - 3065 【AC自动机】
在一个串中找出给定子串出现的次数
#include<bits/stdc++.h>
#define cl(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
char s[1005][150];
struct Trie
{
int nxt[1005*55][128],fail[1005*55],ends[1005*55];
int root,L;
int newnode()
{
rep(i,0,127) nxt[L][i]=-1;
fail[L]=-1;
ends[L++]=-1;
return L-1;
}
void init()
{
L=0;
root = newnode();
}
void ins(char s[],int id)
{
int len = strlen(s);
int now = root;
rep(i,0,len-1)
{
if(nxt[now][s[i]]==-1)
{
nxt[now][s[i]]=newnode();
}
now=nxt[now][s[i]];
}
ends[now]=id;
}
void build()
{
queue<int>q;
fail[root]=root;
rep(i,0,127)
{
if(nxt[root][i]==-1)
{
nxt[root][i] = root;
}
else
{
fail[nxt[root][i]]=root;
q.push(nxt[root][i]);
}
}
while(!q.empty())
{
int now = q.front();
q.pop();
rep(i,0,127)
{
if(nxt[now][i]==-1)
{
nxt[now][i]=nxt[fail[now]][i];
}
else
{
fail[nxt[now][i]]=nxt[fail[now]][i];
q.push(nxt[now][i]);
}
}
}
}
int num[1010];
void query(char buf[],int n)
{
int len = strlen(buf);
int now =root;
for(int i=0; i<=n; i++)
{
num[i]=0;
}
//bool flag=false;
rep(i,0,len-1)
{
now = nxt[now][buf[i]];
int tmp = now;
while(tmp!=root)
{
if(ends[tmp]!=-1)
{
num[ends[tmp]]++;
//flag=true;
}
tmp=fail[tmp];
}
}
rep(i,0,n-1)
{
if(num[i]>0) printf("%s: %d\n",s[i],num[i]);
}
}
};
char buf[2000005];
Trie ac;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
ac.init();
for(int i=0; i<n; i++)
{
scanf("%s",s[i]);
ac.ins(s[i],i);
}
ac.build();
scanf("%s",buf);
ac.query(buf,n);
}
return 0;
}