您的位置:首页 > 其它

HDU 2896 病毒侵袭(AC自动机)

2015-11-07 00:03 441 查看
分析:这也是一道很裸的AC自动机,单词结尾的节点不在是1,而是id,即这个单词的序号,然后用vector把所有序号存在来,一遍去重,然后输出答案就好了。

总的复杂度为o(m*l)

代码:

#include <bits/stdc++.h>
#define LL long long
#define uLL long long
#define FOR(i,x,y)  for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)

using namespace std;

typedef vector <int> VT;

const int maxn = 550*220;
const int maxm = 10010;

struct Trie{
int ch[maxn][128],en[maxn],fail[maxn];
int rt,sz;

void init(){
rt = sz = 0;
memset(ch[rt],-1,sizeof(ch[rt]));
}

void newnode(){
++ sz;
memset(ch[sz],-1,sizeof(ch[sz]));
en[sz] = 0;
}

void insert(char* str,int val){
int len = strlen(str);
int u = rt;
FOR(i,0,len){
if(ch[u][str[i]-' '] == -1){
newnode();
ch[u][str[i]-' '] = sz;
}
u = ch[u][str[i]-' '];
}
en[sz] = val;
}

void build(){
queue <int> q;
FOR(i,0,128){
if(ch[rt][i] == -1){
ch[rt][i] = rt;
}
else{
fail[ch[rt][i]] = rt;
q.push(ch[rt][i]);
}
}
while(!q.empty()){
int u = q.front();  q.pop();
FOR(i,0,128){
if(ch[u][i] == -1){
ch[u][i] = ch[fail[u]][i];
}
else{
fail[ch[u][i]] = ch[fail[u]][i];
q.push(ch[u][i]);
}
}
}
}

VT query(char* str){
int len = strlen(str);
int now = rt;
VT res;
FOR(i,0,len){
now = ch[now][str[i]-' '];
int temp = now;
while(temp != rt){
if(en[temp]){
res.push_back(en[temp]);
}
temp = fail[temp];
}
}
return res;
}
}ac;

int n,m;
char s[maxm];

int main()
{
//freopen("test.in","r",stdin);
while(~scanf("%d",&n)){
ac.init();
FOR(i,1,n+1){
scanf("%s",s);
ac.insert(s,i);
}
ac.build();
scanf("%d",&m);
int id = 0;
FOR(i,1,m+1){
scanf("%s",s);
VT ans = ac.query(s);
if(ans.size()){
++id;
printf("web %d:",i);
sort(ans.begin(),ans.end());
VT :: iterator it = unique(ans.begin(),ans.end());
ans.erase(it,ans.end());
FOR(i,0,(int)ans.size()){
printf(" %d",ans[i]);
}
printf("\n");
}
}
printf("total: %d\n",id);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: