//
AC自动机(Aho-Corasick Automaton Algorithm)
(1)建trie树

(2)广度优先搜索构建所有结点的fail
构造next指针,概括起来是:假如当前的节点的字符为e,沿着它的父亲的next指针走,直到找到一个结点,它的孩子也有e这个字符,然后将当前结点的next指针指向那个结点
有e这个孩子的孩子e。
从root开始广度优先搜索每个点,如果当前搜的点的孩子,与该点的next指针指向的点有相同的孩子,则当前点的孩子指向next指针的孩子,
否则next指针循环搜回去,如果搜不到就指向root。
(3)查找
当时的文本字符串为text,长度为len则有:ptr=root;for i:=1 to len-1 dowhile(ptr->text[i]==NULL&&ptr!=root)ptr=ptr->next;ptr=ptr->child[i];if(ptr==NULL) then ptr=root;//如果搜不到回到根结点HDOJ2002Keywords Search
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8434 Accepted Submission(s): 2828
1 5 she he say shr her yasherhs
3#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; struct trie { trie* next; int isend; trie* child[26]; trie() { isend=0; memset(child,NULL,sizeof(child)); next=NULL; } }*root; void insert(char* str) { int num; int len; trie* ptr; ptr=root; int i; len=strlen(str); for(i=0;i<len;i++) { num=str[i]-'a'; if(ptr->child[num]==NULL) { ptr->child[num]=new trie(); } ptr=ptr->child[num]; } ptr->isend++;//lable the end of string } void ac_automation() { int i; queue<trie*> qu; trie* current=NULL; qu.push(root); trie* fail=NULL; while(!qu.empty()) { current=qu.front(); qu.pop(); /* if(¤t==&0x00370c20) { int debug=1; }*/ //if(current->isend!=1) /* if(current==root) { for(i=0;i<26;i++) { current->child[i]->next=root; qu.push(current->child[i]); continue; }*/ for(i=0;i<26;i++) { if(current->child[i]!=NULL) { fail=current->next; if(current==root) { current->child[i]->next=root; qu.push(current->child[i]); continue; } while(1) { if(fail==NULL) { current->child[i]->next=root; break; } else { if(fail->child[i]!=NULL) { current->child[i]->next=fail->child[i];//have searched the character of current->child[i] break; } } fail=fail->next;//search the character of current->child[i] follow the next pointer } qu.push(current->child[i]);//push the child of current into queue } } } } char text[1000003]; int ans; void query() { int len; len=strlen(text); trie* ptr; ptr=root; int num; int i; //trie* fail=root; trie* temp; for(i=0;i<len;i++) { num=text[i]-'a'; while(ptr->child[num]==NULL&&ptr!=root) { ptr=ptr->next; } ptr=ptr->child[num]; if(ptr==NULL) { ptr=root; } temp=ptr; while(temp!=root&&temp->isend!=-1)//search the matching string follow the next pointer { ans+=temp->isend; temp->isend=-1; temp=temp->next; } } } int main() { int t; int n; int i; char str[52]; scanf("%d",&t); while(t--) { root=new trie(); scanf("%d",&n); for(i=0;i<n;i++) { scanf("%s",str); insert(str); } ac_automation(); scanf("%s",text); ans=0; //len=strlen(text); query(); printf("%d/n",ans); } return 0; }