您的位置:首页 > 其它

hdu 2896 病毒侵袭 ac自动机模板题

2015-09-02 17:53 363 查看
和上一道题不同的是这个题目的mark数组是标记一下到底是第几个串,因为匹配串中不同模式串个数不大于3,不过有可能相同串个数很多- -虽然我数组只开了10过了...还有就是字符的个数从26个飙升到127...所以建立字典树的时候需要做一些小的改动。查找到某个模式串标记一下,排序去重输出即可...

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
int ans[10];
#define N 1000000
struct Trie
{
int next
[130],fail
,mark
;
int root,L;
int newnode()
{
memset(next[L],-1,sizeof(next[L]));
mark[L]=0;
fail[L++]=-1;
return L-1;
}
void go()
{
L=0;
root=newnode();
}
void init(char *v,int id)
{
int p=root;
for(int i=0;v[i];i++)
{
int tep=v[i];
if(next[p][tep]==-1) next[p][tep]=newnode();
p=next[p][tep];
}
mark[p]=id;
}
void bfs()
{
queue<int>q;
q.push(root);
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=0;i<127;i++)
{
if(next[p][i]==-1)
{
if(p==root) next[p][i]=root;
else next[p][i]=next[fail[p]][i];
}
else
{
if(p==root) fail[next[p][i]]=root;
else fail[next[p][i]]=next[fail[p]][i];
q.push(next[p][i]);
}
}
}
}
int finde(char *v)
{
int k=0;
int p=root,q;
for(int i=0;v[i];i++)
{
int tep=v[i];
while(next[p][tep]==-1&&p!=root)
p=fail[p];
p=next[p][tep];
if(p==-1) p=root;
q=p;
while(q!=root)
{
if(mark[q]!=0)
ans[k++]=mark[q];
q=fail[q];
}
}
return k;
}
}ac;
int main()
{
int n,m;
char v[30000];
while(scanf("%d",&n)!=EOF)
{
ac.go();
for(int i=1;i<=n;i++)
{
scanf("%s",v);
ac.init(v,i);
}
ac.bfs();
int cnt=0;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
memset(ans,0,sizeof(ans));
scanf("%s",v);
int k=ac.finde(v);
if(k)
{
printf("web %d:",i);
sort(ans,ans+k);
for(int j=0; j<k; j++)
{
if(ans[j]!=ans[j+1])  printf(" %d",ans[j]);  //为了去重
}
puts("");
cnt++;
}
}
printf("total: %d\n",cnt);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: