题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=2896
本题输出的时候需要排序,其余的是跟上一题差不多,不过不是技术,而是查看是否存在,所以如果该病毒存在,则记录在一个数组里,并不改变结点的数据。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 10000010;
struct Trie_Node
{
int id;
Trie_Node* fail;
Trie_Node* pNext[100];
Trie_Node()
{
id = 0;
fail = NULL;
memset(pNext, NULL, sizeof(pNext));
}
};
Trie_Node* q[MAXN];
Trie_Node* proot;
int head, tail;
int cnt;
int arr[510];
void Insert_Trie(char* str, int id)
{
Trie_Node* p = proot;
for (; *str; str++)
{
int j = *str - 31;
if (p->pNext[j] == NULL)
{
p->pNext[j] = new Trie_Node;
}
p = p->pNext[j];
}
p->id = id;
}
void Build_ac_automaton_fail()
{
head = tail = 0;
proot->fail = NULL;
q[tail++] = proot;
while (head != tail)
{
Trie_Node* temp = q[head++];
Trie_Node* p = NULL;
for(int i = 0; i < 100; ++i)
{
if(temp->pNext[i] != NULL)
{
if(temp == proot)
temp->pNext[i]->fail = proot;
else
{
p = temp->fail;
while(p)
{
if (p->pNext[i] != NULL)
{
temp->pNext[i]->fail = p->pNext[i];
break;
}
p = p->fail;
}
if(p == NULL)
p = p->fail;
}
q[tail++] = temp->pNext[i];
}
}
}
}
void Query_ac_automaton(char* str)
{
cnt = 0;
Trie_Node* p = proot;
int i = 0;
while (str[i])
{
int j = str[i] - 31;
while(p->pNext[j] == NULL && p != proot)
p = p->fail;
p = (p->pNext[j] == NULL) ? proot : p->pNext[j];
Trie_Node* temp = p;
while(temp != proot)
{
if (temp->id)
{
arr[cnt++] = temp->id;
}
temp = temp->fail;
}
i++;
}
}
char s1[10010], s2[210];
int main()
{
int n,m;
int i,j;
while (~scanf("%d", &n))
{
proot = new Trie_Node;
for(i = 1; i <= n; ++i)
{
scanf("%s", s2);
Insert_Trie(s2, i);
}
Build_ac_automaton_fail();
scanf("%d", &m);
int total = 0;
for(i = 1; i <= m; ++i)
{
memset(arr, 0, sizeof(arr));
scanf("%s",s1);
Query_ac_automaton(s1);
if(cnt)
{
printf("web %d:", i);
sort(arr, arr+cnt);
for (j = 0; j < cnt; ++j)
printf(" %d", arr[j]);
printf("\n");
total++;
}
}
printf("total: %d\n",total);
}
return 0;
}