考查知识点:AC自动机
注意:每个网站的“源码字符串长度在7000—10000之间”。
我开了一个字符串char c [300],提交结果不会报字符串溢出,而是wrong answer。
所以别吝惜这点小内存。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define INF 1<<30
#define M 502
#define kind 130
//ascII个数
struct node{
int isword;
node *fail;
node * next[kind];
node()
{
isword=0;
fail=NULL;
mem(next,0);
}
}*root;
set<int> web;
void Insert(node *p,char s[],int x)
{
int index,i=0;
while(s[i])
{
index=(int)s[i];
if(p->next[index]==NULL)
p->next[index]=new node;
p=p->next[index];
i++;
}
p->isword=x;
}
void build_ac_automation(node *p)
{
queue<node*>Q;
Q.push(p);
node *temp;
while(!Q.empty())
{
temp=Q.front();Q.pop();
p=NULL;
for(int i=0; i<kind; i++)
if(temp->next[i]!=NULL)
{
if(temp==root)temp->next[i]->fail=root;
else
{
p=temp->fail;//p向着temp的失败指针向上走
while(p!=NULL)
{
if(p->next[i]!=NULL)
{
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;//p向着自己的失败指针向上走
}
if(p==NULL)temp->next[i]->fail=root;
}
Q.push(temp->next[i]);
}
}
}
void query(node *p,char s[])
{
int i=0,index;
while(s[i])
{
index=(int)s[i];
while(p->next[index]==NULL && p!=root)p=p->fail;
p=p->next[index];
if(p==NULL)p=root;
node *temp=p;
while(temp!=root)
{
if(temp->isword)
web.insert(temp->isword);
//cout<<temp->isword;
temp=temp->fail;
}
i++;
}
}
void myfree(node *p)
{
for(int i=0;i<kind;i++)
if(p->next[i]!=NULL)
myfree(p->next[i]);
delete p;
}
int main()
{
int m,n,i,j,total;
char s[202];
char virus[10002];//"源码字符串长度在7000—10000之间。"我直接用s[]这里错了3次
while(~scanf("%d",&m))
{
root=new node;
total=0;
for(i=1;i<=m;i++)
{
scanf("%s",s);
Insert(root,s,i);
}
build_ac_automation(root);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",virus);
web.clear();
query(root,virus);
if(web.size()>0)
{
total++;
printf("web %d:",i);
set<int>::iterator it;
for(it=web.begin();it!=web.end();it++)
printf(" %d",*it);
printf("\n");
}
}
printf("total: %d\n",total);
myfree(root);
}
return 0;
}