题目大意:给一些病毒字符串,问一些网址中有哪些病毒。
思路:AC自动机挺裸的题,但是听说Trie图还好写,时间还快,以后就不写AC自动机了,直接啥题都上Trie图吧。
注意:此题输出结尾要加回车,否则会PE!
CODE:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct Trie{
Trie *son[130],*fail;
int id;
Trie() {
id = 0;
memset(son,NULL,sizeof(son));
}
}*root = new Trie();
int cnt,asks;
char s[10010];
bool v[1010];
int ill[1010];
inline void Insert(char *s,int p)
{
Trie *now = root;
while(*s != '\0') {
if(now->son[*s] == NULL)
now->son[*s] = new Trie();
now = now->son[*s];
++s;
}
now->id = p;
}
void MakeTrieGraph()
{
static queue<Trie *> q;
while(!q.empty()) q.pop();
for(int i = 0; i < 128; ++i)
if(root->son[i] != NULL)
root->son[i]->fail = root,q.push(root->son[i]);
while(!q.empty()) {
Trie *now = q.front(); q.pop();
for(int i = 0; i < 128; ++i)
if(now->son[i] != NULL) {
Trie *temp = now->fail;
while(temp != root && temp->son[i] == NULL)
temp = temp->fail;
if(temp->son[i] != NULL)
temp = temp->son[i];
now->son[i]->fail = temp;
q.push(now->son[i]);
}
else now->son[i] = now->fail->son[i] ? now->fail->son[i]:root;
}
}
inline void Ask(char *s)
{
Trie *now = root;
while(*s != '\0') {
if(now->son[*s] != NULL)
now = now->son[*s];
for(Trie *temp = now; temp != root; temp = temp->fail)
if(temp->id && !v[temp->id])
v[temp->id] = true,ill[++ill[0]] = temp->id;
++s;
}
}
int main()
{
cin >> cnt;
for(int i = 1; i <= cnt; ++i) {
scanf("%s",s);
Insert(s,i);
}
MakeTrieGraph();
cin >> asks;
int ans = 0;
for(int i = 1; i <= asks; ++i) {
memset(v,false,sizeof(v));
memset(ill,0,sizeof(ill));
scanf("%s",s);
Ask(s);
if(ill[0]) {
++ans;
sort(ill + 1,ill + ill[0] + 1);
printf("web %d:",i);
for(int j = 1; j <= ill[0]; ++j)
printf(" %d",ill[j]);
puts("");
}
}
printf("total: %d\n",ans);
return 0;
}