题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896
题目大意:给定n个病毒代码和m个网站源码,问每个网站源码包含哪些病毒。
解题思路:用n个病毒代码构造一棵trie树,再增加fail指针。最后只要进行查询就可以了,差不多就是模板题。最后将求得的病毒序号排序输出即可。
测试数据:
3
aaabbaacc
代码:
#include <iostream> #include <string.h> #include <algorithm> using namespace std; struct node { int flag,rec; node *next[100],*fail; node () { flag = rec = 0; memset(next,NULL,sizeof(next)); fail = NULL; } }*q[1000010]; int n,m,cnt,tot,cas; int head,tail,arr[501]; char key[201],str[100010]; void Insert(node *root,char *str,int loc) { int i = 0,k; node *p = root; while (str[i]) { k = str[i++] - 31; if (p->next[k] == NULL) p->next[k] = new node(); p = p->next[k]; } p->flag = 1; p->rec = loc; } void my_accept(node *root) { //构造失败指针 root->fail = NULL; q[head++] = root; while (head != tail) { node *temp = q[tail++]; //获取头结点 node *p = NULL; for (int i = 0; i < 100; ++i) { //遍历每个子节点 if (temp->next[i] != NULL) { //子节点存在的情况 if (temp == root) temp->next[i]->fail = root;//失败节点指向头结点 else { //回溯 p = temp->fail; while (p != NULL) { if (p->next[i] != NULL) { //找到匹配数 temp->next[i]->fail = p->next[i]; break; } p = p->fail; } if (p == NULL) temp->next[i]->fail = root; }//else q[head++] = temp->next[i]; }//if ( != NULL }//for i }//while head != tail } void Search(node *root,char *str) { int i = 0,k; node *p = root,*temp; while (str[i]) { k = str[i++] - 31; while (p->next[k] == NULL && p != root) p = p->fail; //往前回溯求最长后缀 p = (p->next[k] ? p->next[k] : root); temp = p; while (temp != root) { if (temp->flag == 1) arr[cnt++] = temp->rec; temp = temp->fail; } } } int main() { int i,j,k; while (scanf("%d",&n) != EOF) { node *root = new node(); for (i = 1; i <= n; ++i) scanf("%s",key),Insert(root,key,i); tot = head = tail = 0; my_accept(root); scanf("%d",&m); for (i = 1; i <= m; ++i) { scanf("%s",str); cnt = 0; Search(root,str); if (cnt == 0) continue; tot++; printf("web %d:",i); sort(arr,arr+cnt); for (j = 0; j < cnt; ++j) printf(" %d",arr[j]); printf("\n"); } printf("total: %d\n",tot); } }
本文ZeroClock原创,但可以转载,因为我们是兄弟。