AC模板,输出匹配的各个模式串及其在文本串的位置,代码里的注释应该够了!
1 #include<iostream> 2 #include<cstring>//对应memset()函数 3 #include<queue> 4 #include<vector> 5 using namespace std; 6 struct Node 7 { 8 Node *fail,*son[26]; 9 int cnt;//cnt为0表示初始化,cnt为-1表示已经匹配过 10 int idx;//如果是个模式串匹配完成的单词节点,则idx是该节点对应的模式串在pattern里的下标,否则初始化为0 11 Node()//初始化函数 12 { 13 fail=NULL; 14 memset(son,NULL,sizeof(son)); 15 cnt=0; 16 idx=0; 17 } 18 }*root; 19 string str;//存放不定长度的待匹配的文本串 20 queue<Node*>q; 21 vector<string>pattern;//存放不定个数和长度的模式串 22 23 void Init(){//建立trie树 24 string s; 25 root=new Node(); 26 Node*p=NULL; 27 while(cin>>s){ 28 if(s=="0") break;//模式串输入结束标志 29 pattern.push_back(s);// 30 } 31 for(int i=0;i<pattern.size();i++){ 32 p=root; 33 for(int j=0;j<pattern[i].size();j++){//模式串逐个处理 34 int index=pattern[i][j]-'a'; 35 if(p->son[index]==NULL)//空,则新建 36 p->son[index]=new Node(); 37 p=p->son[index];//往下走 38 } 39 ++p->cnt;//一个模式串匹配结束,该节点cnt为正数 40 p->idx=i;//记录在模式串里下标 41 } 42 } 43 44 void Build_Fail(){//BFS,建立fail函数, 45 //root的子节点的失败指针都指向root。 46 //节点(字符为x)的失败指针指向:从X节点的父节点的fail节点回溯直到找到某节点的子节点也是字符x,没有找到就指向root。 47 root->fail=root; 48 q.push(root); 49 Node *p,*t,*tmp; 50 while(!q.empty()){ 51 tmp=p=q.front(); 52 q.pop(); 53 int b=q.size(); 54 for(int i=0;i<26;i++){ 55 p=tmp; 56 t=p->son[i]; 57 if(t!=NULL){ 58 if(p==root)t->fail=root;//第二层的fail全部指向root 59 else{ 60 while(p!=root){ 61 p=p->fail; 62 if(p->son[i]){ 63 t->fail=p->son[i]; 64 break; 65 } 66 } 67 if(p->son[i]==NULL)t->fail=root; 68 } 69 q.push(t);//入队 70 } 71 } 72 } 73 } 74 75 void Work(){/*从root节点开始,每次根据读入的字符沿着自动机向下移动。 76 当读入的字符,在分支中不存在时,递归走失败路径。 77 如果走失败路径走到了root节点, 则跳过该字符,处理下一个字符。 78 因为AC自动机是沿着输入文本的最长后缀移动的,所以在读取完所有输入文本后,最后递归走失败路径,直到到达根节点, 这样可以检测出所有的模式。*/ 79 cin>>str; 80 Node *p=root,*t; 81 int index,ans=0; 82 for(int i=0;i<str.size();i++){ 83 index=str[i]-'a'; 84 while(p->son[index]==NULL&&p!=root)p=p->fail; 85 p=p->son[index]; 86 if(p==NULL)p=root; 87 t=p; 88 while(t!=root&&t->cnt!=-1){ 89 if(t->cnt) 90 cout<<i-pattern[t->idx].size()+1<<'\t'<<t->idx<<'\t'<<pattern[t->idx]<<endl; 91 ans+=t->cnt; 92 t->cnt=-1; 93 t=t->fail; 94 } 95 } 96 } 97 98 int main(){ 99 int T; 100 freopen("AC.in","r",stdin); 101 cin>>T; 102 while(T--){ 103 Init(); 104 Build_Fail(); 105 Work(); 106 } 107 fclose(stdin); 108 return 0; 109 } 110 /* 111 2 112 she 113 he 114 his 115 her 116 0 117 shers 118 xabc 119 abc 120 b 121 a 122 0 123 xabc 124 */