标签:enter -- namespace void 封装 字典树 pid int tab
这题是AC自动机的模板题,AC自动机是结合了字典树,和KMP两种算法产生的,去年为了学习AC自动机去看了前面说的两种算法,但是可能因为KMP当时理解的不够透彻所以这题当时也只是半背代码的做出来了,没多久就忘了。经过那么久的学习感觉KMP掌握的差不多了,今天回顾了一下AC自动机,并记录一下模板
Accepted | 2222 | 327MS | 56848K | 1991 B | G++ |
#include "cstdio" #include "cstring" #include "cstdlib" #include "queue" using namespace std; const int MAXS = 1000005; const int MAXP = 55; const int SIZE = 26; struct Tree { int tail; Tree* next[SIZE]; Tree* fail; }* root; char p[MAXP], s[MAXS]; Tree* init() { Tree* point = (Tree*)malloc(sizeof(Tree)); point->tail = 0; memset(point->next, NULL, sizeof(point->next)); point->fail = NULL; return point; } void insert(char* p) { Tree* point = root; for (int i = 0; p[i]; i++) { int index = p[i] - ‘a‘; if (point->next[index] == NULL) { point->next[index] = init(); } point = point->next[index]; } point->tail++; } void build() { queue<Tree*> q; Tree* point; Tree* p1; Tree* p2; q.push(root); while (!q.empty()) { point = q.front(); q.pop(); for (int i = 0; i < SIZE; i++) { if (point->next[i] != NULL) { p1 = point->fail; p2 = point->next[i]; while (p1 != NULL) { if (p1->next[i] != NULL) { p2->fail = p1->next[i]; break; } p1 = p1->fail; } if (p1 == NULL) { p2->fail = root; } q.push(p2); } } } } int query(char* s) { int cnt = 0; Tree* p1; Tree* p2; p1 = root; for (int i = 0; s[i]; i++) { int index = s[i] - ‘a‘; while (p1 != root && p1->next[index] == NULL) { p1 = p1->fail; } p1 = p1->next[index]; if (p1 == NULL) { p1 = root; } p2 = p1; while (p2 != root && p2->tail != -1) { cnt += p2->tail; p2->tail = -1; p2 = p2->fail; } } return cnt; } void clear(Tree* point) { for (int i = 0; i < SIZE; i++) { if (point->next[i] != NULL) { clear(point->next[i]); } } free(point); } int main() { int t, n; scanf("%d", &t); while (t--) { root = init(); scanf("%d", &n); while (n--) { scanf("%s", p); insert(p); } scanf("%s", s); build(); printf("%d\n", query(s)); clear(root); root = NULL; } return 0; }
build的时候网上的代码都是用自己写的队列,我一开始用自己写的队列运行时间达到了171ms,确实比库里封装的快不少,但是我还是喜欢用库里的比较保险。弄懂了KMP和字典树看一下网上的讲解就好理解了。
HDU-2222-Keywords Search(AC自动机模板)
标签:enter -- namespace void 封装 字典树 pid int tab
原文地址:https://www.cnblogs.com/Angel-Demon/p/10358416.html