其实本题比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; }
HDU 3065 病毒侵袭持续中 AC自动机题解,布布扣,bubuko.com
时间: 2024-10-08 10:17:13