HDU 3065 病毒侵袭持续中 AC自动机题解

来源:互联网 发布:图片纹理算法 编辑:程序博客网 时间:2024/06/16 01:19

其实本题比HDU的病毒侵袭1还简单,不过有一个陷阱卡到我了:就是搜索text的时候,当遇到的字母不是大写字母的时候,那么就要重新从根节点开始搜索,否则就会答案错误。

那么一点陷阱,居然没想到啊。

教训啊:看来对不太平常的地方,需要更加深入的思考,才能发现其中的陷阱,否则就WA了。


#include <stdio.h>#include <string.h>#include <queue>using std::queue;const int MAX_N = 1001;const int VIRUS_LEN = 51;const int TXT_LEN = 2000001;const int ARR_SIZE = 26;char Virus[MAX_N][VIRUS_LEN], txt[TXT_LEN];int IdNum[MAX_N];inline int getIndex(char a) { return a - 'A'; }struct Node{int n, num;Node *fail;Node *arr[ARR_SIZE];};Node pool[MAX_N*VIRUS_LEN], *Trie;int poolID;void clearNode(Node *rt){rt->n = rt->num = 0;rt->fail = NULL;memset(rt->arr, 0, sizeof(rt->arr));}void insert(char *w, int num){Node *pCrawl = Trie;for ( ; *w; w++){int id = getIndex(*w);if (!pCrawl->arr[id]){pCrawl->arr[id] = &pool[poolID++];clearNode(pCrawl->arr[id]);}pCrawl = pCrawl->arr[id];}pCrawl->n++;pCrawl->num = num;}void buildFail(){queue<Node *> qu;qu.push(Trie);while (!qu.empty()){Node *pCrawl = qu.front(); qu.pop();for (int i = 0; i < ARR_SIZE; i++){if (!pCrawl->arr[i]) continue;pCrawl->arr[i]->fail = Trie;Node *fail = pCrawl->fail;while (fail){if (fail->arr[i]){pCrawl->arr[i]->fail = fail->arr[i];break;}fail = fail->fail;}qu.push(pCrawl->arr[i]);}}}void search(){Node *pCrawl = Trie;for (char *p = txt; *p; p++){if (*p < 'A' || 'Z' < *p){pCrawl = Trie;continue;}int id = getIndex(*p);while (!pCrawl->arr[id] && pCrawl != Trie) pCrawl = pCrawl->fail;if (pCrawl->arr[id]){pCrawl = pCrawl->arr[id];for (Node *tmp = pCrawl; tmp && tmp->n; tmp = tmp->fail){if (tmp->n) IdNum[tmp->num]++;}}}}int main(){int n;Trie = &pool[0];while (scanf("%d", &n) != EOF){getchar();clearNode(Trie);poolID = 1;for (int i = 0; i < n; i++){gets(Virus[i]);insert(Virus[i], i);}buildFail();memset(IdNum, 0, sizeof(int) * n);gets(txt);search();for (int i = 0; i < n; i++){if (IdNum[i]) printf("%s: %d\n",Virus[i], IdNum[i]); }}return 0;}



1 0
原创粉丝点击