#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h> //hdu 3065
#include <queue> //AC自动机模板题(动态建立及释放空间)
using namespace std;
char a[1010][55], b[2000010];
int c[1002];
struct trie
{
trie *next[128];
trie *fail; //失败指针,类似于kmp中的next
int g;
int vis; //标记结尾
trie()
{
for(int t=0; t<128; ++t)
next[t]=NULL;
fail=NULL;
g=vis=0;
}
}*root;
void create(char *p, int num) //建立字典树
{
int t=0, k, j=strlen(p);
trie *q=root;
while(t<j)
{
k=p[t]-31;
if(!q->next[k])
{
q->next[k]=new trie();
}
q=q->next[k];
t++;
}
q->g=num; //g表示字符串的序号
q->vis=1; //vis表示字符串结束的节点标志
return ;
}
void makefail() //fail指针
{
queue<trie *> q;
q.push(root);
while(!q.empty())
{
trie *p=q.front(), *temp;
q.pop();
for(int t=0; t<128; ++t)
{
if(p->next[t])
{
temp=p;
if(p==root)
{
temp->next[t]->fail=p;
}
else
{
while(temp->fail)
{
if(temp->fail->next[t])
{
p->next[t]->fail=temp->fail->next[t];
break;
}
temp=temp->fail;
}
if(!temp->fail)
{
p->next[t]->fail=root;
}
}
q.push(p->next[t]);
}
}
}
return ;
}
void f(char *p)
{
int t, k, j=strlen(p);
trie *q=root, *temp;
memset(c, 0, sizeof(c));
for(t=0; t<j; ++t)
{
k=p[t]-31;
while(q!=root&&q->next[k]==NULL)
{
q=q->fail;
}
q=q->next[k];
if(!q)q=root;
temp=q;
while(temp!=root&&temp->vis) //找到后
{
c[temp->g]++; //修改的部分,前面都是模板
temp=temp->fail; //返回到temp的fail指针
}
}
return ;
}
void del(trie *root) //释放空间
{
trie *p=root;
for(int t=0; t<128; ++t)
{
if(p->next[t])
del(p->next[t]);
}
delete p;
}
int main()
{
int n, t;
while(scanf("%d", &n)!=EOF)
{
root=new trie();
for(t=1; t<=n; ++t)
{
scanf("%s", &a[t]);
create(a[t], t);
}
makefail();
scanf("%s", b);
f(b);
for(t=1; t<=n; ++t)
{
if(c[t])
{
printf("%s: %d\n", a[t], c[t]);
}
}
del(root);
}
return 0;
}
hdu3065 AC自动机
最新推荐文章于 2019-07-24 09:24:46 发布