二次联通门 : HDU 2222 Keywords Search
/* HDU 2222 Keyword Search 重新规范一下AC自动机的写法。。 */ #include <cstring> #include <cstdio> #include <queue> #include <cstdlib> #define Max 1000009 void read (int &now) { now = 0; register char word = getchar (); while (word < '0' || word > '9') word = getchar (); while (word >= '0' && word <= '9') { 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; for (read (T); T --; ) { Root = new Trie_Data; for (read (N); N --; ) { scanf ("%s", line); Make.Insert (line); } Make.AC_Build (); scanf ("%s", line); printf ("%d ", Make.Query (line)); } return 0; }