二次联通门 : luogu P3808 【模板】AC自动机(简单版)
/* luogu P3808 【模板】AC自动机(简单版) 手速越来越快了 10分钟一个AC自动机 一遍过编译 + 一边AC 感觉不错 我也就做做板子题了。。 */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> #define Max 1000009 void read (int &now) { register char word = getchar (); for (now = 0; !isdigit (word); word = getchar ()); for (; isdigit (word); now = now * 10 + word - ‘0‘, word = getchar ()); } struct Trie_Data { Trie_Data *child[26]; Trie_Data *Fail; int Count; Trie_Data () { for (int i = 0; i < 26; i ++) this->child[i] = NULL; Fail = NULL; Count = 0; } }; Trie_Data *Root; std :: queue <Trie_Data *>Queue; class AC_Type { public : void Insert (char *key) { Trie_Data *now = Root; Trie_Data *pos; int Id; int Len = strlen (key); for (int i = 0; i < Len; i ++) { Id = key[i] - ‘a‘; if (now->child[Id] == NULL) now->child[Id] = new Trie_Data; now = now->child[Id]; } now->Count ++; } void AC_Build () { Queue.push (Root); Trie_Data *now; Trie_Data *pos; while (!Queue.empty ()) { pos = NULL; now = *&Queue.front (); Queue.pop (); for (int i = 0; i < 26; i ++) { if (now->child[i] == NULL) continue; if (now == Root) now->child[i]->Fail = Root; else { pos = now->Fail; for (; pos; pos = pos->Fail) if (pos->child[i] != NULL) { now->child[i]->Fail = pos->child[i]; break; } if (pos == NULL) now->child[i]->Fail = Root; } Queue.push (now->child[i]); } } } int Query (char *key) { int Answer = 0; int Len = strlen (key); int Id; Trie_Data *now = Root; for (int i = 0; i < Len; i ++) { Id = key[i] - ‘a‘; while (now->child[Id] == NULL && now != Root) now = now->Fail; now = now->child[Id]; if (now == NULL) now = Root; Trie_Data *pos = now; for (; pos != Root && pos->Count >= 0; pos = pos->Fail) { Answer += pos->Count; pos->Count = -1; } } return Answer; } }; AC_Type Make; char line[Max]; int main (int argc, char *argv[]) { int T, N; Root = new Trie_Data; for (read (N); N --; ) { scanf ("%s", line); Make.Insert (line); } Make.AC_Build (); scanf ("%s", line); printf ("%d\n", Make.Query (line)); return 0; }
时间: 2024-12-28 11:22:46