AC自动机算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一,由Alfred V.Aho发明,他还是编译原理红龙书的作者之一。
AC自动机算法是字典树和KMP算法的结合,主要用于多字符串匹配,比如给定若干个单词,再给定一篇文章,问在文章中出现了多少个单词。AC自动机算法可以快速解决此类问题。
例题:hdu 2222
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18971 Accepted Submission(s): 6329
1 5 she he say shr her yasherhs
3
#include <stdio.h> #include <memory.h> #include <iostream> using namespace std; //字典树结点 struct TRIE_TREE_NODE { TRIE_TREE_NODE *child[26]; int count; TRIE_TREE_NODE *fail; //失败指针 }; TRIE_TREE_NODE *ROOT; //初始化一个字典树结点 void init_trie_tree_node(TRIE_TREE_NODE *node) { memset(node->child ,NULL ,26*4); node->count = 0; node->fail = NULL; } void insert_into_trie_tree(TRIE_TREE_NODE *node ,char *str) { int i; unsigned char ch; for(i = 0 ; '\0' != str[i] ;i ++) { ch = str[i]-'a'; if(NULL == node->child[ch]) { node->child[ch] = (TRIE_TREE_NODE*)malloc(sizeof(TRIE_TREE_NODE)); init_trie_tree_node(node->child[ch]); } node = node->child[ch]; } node->count ++; } TRIE_TREE_NODE *queue[1000000]; //构造一颗字典树每个结点的失败指针 void build_fail_pointer(TRIE_TREE_NODE *root) { int head ,rear ,i; TRIE_TREE_NODE *cur_node ,*t; root->fail = root; head = rear = 0; queue[rear++] = root; while(head < rear) { cur_node = queue[head++]; for(i = 0 ; i < 26 ;i ++) { if(NULL != cur_node->child[i]) { if(root == cur_node) cur_node->child[i]->fail = root; else { t = cur_node->fail; while(root != t && NULL == t->child[i]) t = t->fail; if(NULL != t->child[i]) t = t->child[i]; cur_node->child[i]->fail = t; } queue[rear++] = cur_node->child[i]; } } } } int search(TRIE_TREE_NODE *root ,char *str) { int count = 0 ,i; unsigned char ch; TRIE_TREE_NODE *cur_node = root ,*t; for(i = 0 ; '\0' != str[i] ;i ++) { ch = str[i]-'a'; while(NULL == cur_node->child[ch] && cur_node != root) cur_node = cur_node->fail; if(cur_node->child[ch] != NULL ) cur_node = cur_node->child[ch]; t = cur_node; while(root != t && t->count != -1) { count += t->count; t->count = -1; t = t->fail; } } return count; } char str[1000100]; void release_trie_tree(TRIE_TREE_NODE *root) { int i; for(i = 0 ;i < 26 ;i ++) { if(NULL != root->child[i]) release_trie_tree(root->child[i]); } free(root); } int main() { int t ,n ,i; cin >> t; while(t--) { ROOT = (TRIE_TREE_NODE*)malloc(sizeof(TRIE_TREE_NODE)); init_trie_tree_node(ROOT); cin >> n; for(i = 0 ;i < n ;i ++) { scanf("%s" ,str); insert_into_trie_tree(ROOT ,str ); } build_fail_pointer(ROOT); scanf("%s" ,str); cout<<search(ROOT ,str)<<endl; release_trie_tree(ROOT); } return 0; }