AC自动机是著名的多模式匹配算法,给出n个单词和一篇含有m个单词的文章,找出n个单词中有多少是在文章中出现过。
AC自动机的构造分为三步:构造trie树,构造fail指针,模式串匹配。而常用的单模式串匹配主要用kmp算法,多模式匹配与之有相似之处,因此要学习AC自动机,需要有trie树和kmp算法的知识。
下边链接中有对AC自动机以及它的构造比较清晰的描述,笔者也是在一次面试中第一次接触到AC自动机,学习之后特来实现一下
http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
1 HDU 2222 2 3 #include <stdio.h> 4 5 struct node 6 { 7 node * fail; 8 node * next[26]; 9 int flag; 10 node() 11 { 12 fail=NULL; 13 for(int i=0;i<26;i++) 14 next[i]=NULL; 15 flag=0; 16 } 17 }; 18 19 char content[1000001]; 20 char seq[51]; 21 node * que[510000]; 22 23 void insert(char * str,node * root) 24 { 25 node * p = root; 26 int t; 27 while(*str) 28 { 29 t=*str-'a'; 30 if(p->next[t]==NULL) 31 p->next[t]=new node(); 32 p=p->next[t]; 33 str++; 34 } 35 p->flag++; 36 } 37 38 void build_ac(node * root) 39 { 40 node *p,*q; 41 int head,tail; 42 head=tail=0; 43 root->fail=NULL; 44 que[head++]=root; 45 while(tail<head) 46 { 47 p=que[tail++]; 48 for(int i=0;i<26;i++) 49 { 50 if(p->next[i]) 51 { 52 if(p==root) 53 p->next[i]->fail=root; 54 else 55 { 56 q=p->fail; 57 while(q!=NULL) 58 { 59 if(q->next[i]) 60 { 61 p->next[i]->fail=q->next[i]; 62 break; 63 } 64 q=q->fail; 65 } 66 if(q==NULL) 67 p->next[i]->fail=root; 68 } 69 que[head++]=p->next[i]; 70 } 71 } 72 } 73 } 74 75 int query(char * content,node * root) 76 { 77 node * p = root,*q,*tmp; 78 int cnt=0; 79 int t; 80 while(*content) 81 { 82 t=*content-'a'; 83 while(p!=NULL && p->next[t]==NULL) 84 p=p->fail; 85 if(p==NULL) 86 p=root; 87 else 88 { 89 p=p->next[t]; 90 q=p; 91 while(q!=root) 92 { 93 if(q->flag>0) 94 { 95 cnt+=q->flag; 96 q->flag=-1; 97 } 98 q=q->fail; 99 } 100 } 101 content++; 102 } 103 return cnt; 104 } 105 106 int main(int argc, char * argv[]) 107 { 108 freopen("in","r",stdin); 109 int t,n; 110 scanf("%d",&t); 111 while(t--) 112 { 113 scanf("%d",&n); 114 node * root = new node(); 115 for(int i=0;i<n;i++) //构建trie树 116 { 117 scanf("%s",seq); 118 insert(seq,root); 119 } 120 scanf("%s",content); 121 build_ac(root); //构造fail指针 122 printf("%d\n",query(content,root)); //模式串匹配 123 } 124 return 0; 125 }