AC自动机的模板题。
题意:给定n个字符串和一段文本,统计每个字符串在文本中分别出现的次数。
注意点:这里输入单词的时候给每个单词分布一个id,然后在统计次数的时候根据id增加数组的次数就可以了。(这里用kuangbin大神的模板)
code:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
char t[1005][55],s[2000005];
const int ma=50010,kd=26;
int ans[1005];
struct Trie
{
int next[ma][kd],fail[ma],en[ma];
int root,L,id;
int newnode()
{
for(int i=0; i<kd; ++i)
next[L][i]=-1;
en[L++]=0;
return L-1;
}
void init()
{
L=0;
id=0;
root=newnode();
}
void Insert(char buf[])
{
int len=strlen(buf);
int now=root;
for(int i=0; i<len; ++i)
{
if(next[now][buf[i]-'A']==-1)
next[now][buf[i]-'A']=newnode();
now=next[now][buf[i]-'A'];
}
en[now]=++id;
}
void build()
{
queue<int> q;
fail[root]=root;
for(int i=0; i<26; ++i)
{
if(next[root][i]==-1)
next[root][i]=root;
else
{
fail[next[root][i]]=root;
q.push(next[root][i]);
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0; i<26; ++i)
if(next[now][i]==-1)
next[now][i]=next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
q.push(next[now][i]);
}
}
}
void query(char buf[])
{
memset(ans,0,sizeof(ans));
int len=strlen(buf);
int now=root;
for(int i=0; i<len; ++i)
{
if(buf[i]>='A'&&buf[i]<='Z')
{
now=next[now][buf[i]-'A'];
int temp=now;
while(temp!=root)
{
ans[en[temp]]++;
temp=fail[temp];
}
}
else now=root;
}
}
};
Trie ac;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
ac.init();
for(int i=1; i<=n; ++i) //这里字符串的下标要从1开始,因为前面分布是 ++id
{
scanf("%s",t[i]);
ac.Insert(t[i]);
}
ac.build();
scanf("%s",s);
ac.query(s);
for(int i=1; i<=n; ++i)
{
if(ans[i])
printf("%s: %d\n",t[i],ans[i]);
}
}
return 0;
}