病毒侵袭
题意:N个病毒编码,M个网站编码,问每个网站编码中包含那几种病毒;
思路:多串匹配多串,很明显是AC自动机,而且是个模板题;
之前写使用的指针写的,结果ML了,然后就找到了一个不用指针的模板,将指针改为了二维数组,这样就不会ML了;
#include <bits/stdc++.h>
using namespace std;
int n, m;
struct Trie{
int next[100010][128], fail[100010], end[100010];
int root, L;
int new_node(){
for(int i=0; i<128; i++){
next[L][i]=-1;
}
fail[L]=-1;
end[L++]=-1;
return L-1;
}
void init(){
L=0;
root=new_node();
}
void insert(char *s, int id){
int p=root, q;
int len=strlen(s);
int x;
for(int i=0; i<len; i++){
x=s[i];
if(next[p][x]==-1){
q=new_node();
next[p][x]=q;
}
p=next[p][x];
}
end[p]=id;
}
void define_fail(){
queue<int> que;
fail[root]=root;
for(int i=0; i<128; i++){
if(next[root][i]==-1) next[root][i]=root;
else{
fail[next[root][i]]=root;
que.push(next[root][i]);
}
}
while(!que.empty()){
int p=que.front();
que.pop();
for(int i=0; i<128; i++){
if(next[p][i]==-1) next[p][i]=next[fail[p]][i];
else{
fail[next[p][i]]=next[fail[p]][i];
que.push(next[p][i]);
}
}
}
}
bool vis[510];
bool query(char *s, int id){
int len=strlen(s);
int p=root;
memset(vis, false, sizeof(vis));
bool flag=false;
int x;
for(int i=0; i<len; i++){
x=s[i];
p=next[p][x];
int temp=p;
while(temp!=root){
if(end[temp]!=-1){
vis[end[temp]]=true;
flag=true;
}
temp=fail[temp];
}
}
if(!flag) return false;
printf("web %d:", id);
for(int i=1; i<=n; i++){
if(vis[i]) printf(" %d", i);
}
puts("");
return true;
}
};
char vir[210], web[10010];
Trie ac;
int main(){
scanf("%d", &n);
ac.init();
for(int i=1; i<=n; i++){
scanf("%s", vir);
ac.insert(vir, i);
}
ac.define_fail();
int tot=0;
scanf("%d", &m);
for(int i=1; i<=m; i++){
scanf("%s", web);
if(ac.query(web, i)) tot++;
}
printf("total: %d\n", tot);
return 0;
}