今天学了AC自动机,可以说AC自动机是把匹配的串建立成为一颗trie,然后就和kmp 是一样的
题意:判断在一篇文章中有多少单词出现过,并输出来
#include<cstdio> #include<cstring> #include<map> #include<queue> #include<iostream> using namespace std; const int maxn = 1000007; int cnt; struct Node{ Node *fail; Node *next[27]; int count,id; Node(){ memset(next,NULL,sizeof(next)); fail = NULL; count = 0 ,id = -1; } }; char word[200][108]; int keymap[200],ret[200]; char str[maxn]; int Max; void insert(int pos,char *str,Node *root){ Node *p = root; int i=0,index; while(str[i]){ index = str[i] - 'a'; if(p -> next[index] == NULL) p -> next[index] = new Node(); p = p->next[index];i++; } if(!p->count){ p->id = cnt++; p ->count = 1; } keymap[pos] = p->id; } void Build_AC_auto(Node *root){ queue <Node*> s; root -> fail = NULL; s.push (root); while(!s.empty()){ Node *tmp = s.front();s.pop(); Node *p = NULL; for(int i=0;i<26;i++){ if(tmp ->next[i]){ if(tmp == root)tmp->next[i]->fail = root; else { p = tmp->fail; while(p){ if(p->next[i]){ tmp -> next[i] -> fail = p -> next[i]; break; } p = p -> fail; } if(!p)tmp->next[i]->fail = root; } s.push(tmp -> next[i]); } } } } void query(Node *root){ int i=0; Node *p = root; while(str[i]){ int index = str[i] - 'a'; while(!p->next[index] && p!=root)p = p->fail; p = p->next[index]; p = (p == NULL) ? root : p; Node *tmp = p; while(tmp !=root ){//puts("yes"); if(tmp ->count){ ret[tmp ->id]++; if(ret[tmp ->id]> Max){ Max = ret[tmp -> id]; } } tmp = tmp->fail; } i++; } } int main(){ int t,n,m; freopen("input.txt","r",stdin); scanf("%d",&t); while(t --){ Max = 0;cnt =0 ; Node *root = new Node(); scanf("%d",&n); memset(ret,0,sizeof(ret)); for(int i=0;i<n;i++){ scanf("%s",word[i]); insert(i,word[i],root); } Build_AC_auto(root); scanf("%s",str); query(root); printf("%d\n",Max); for(int i=0;i<n;i++){ if(ret[keymap[i]]== Max){ printf("%s\n",word[i]); } } } }
时间: 2024-11-13 02:36:45