AC自动机

来源:互联网 发布:ubuntu samba 安装 编辑:程序博客网 时间:2024/06/10 03:38

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N=30;struct Trie{Trie *fail;Trie *next[N];int count;int id;Trie(){fail=NULL;count=0;id=-1;memset(next,NULL,sizeof(next));}}*q[500010];//存取每个节点char word[1010][60];char str[2000010];int head,tail,ID;int vis[1010];int query(Trie*root);void Insert(char *str,Trie *Root){Trie *loc=Root;int i=0;while(str[i]!='\0'){int id=str[i]-'a';if(loc->next[id]==NULL)loc->next[id]=new Trie();loc=loc->next[id];i++;}loc->count++;loc->id=ID++;}void AC_automation(Trie *Root){Root->fail=NULL;q[head++]=Root;Trie *cur,*tmp;while(head!=tail){cur=q[tail++];tmp=NULL;for(int i=0;i<30;i++){if(cur->next[i]!=NULL){if(cur==Root)cur->next[i]->fail=Root;else{tmp=cur->fail;while(tmp!=NULL){if(tmp->next[i]!=NULL){cur->next[i]->fail=tmp->next[i];break;}tmp=tmp->fail;}if(tmp==NULL)cur->next[i]->fail=Root;}q[head++]=cur->next[i];}}}}int main(){//freopen("input.txt","r",stdin);int n;while(~scanf("%d",&n)){memset(vis,0,sizeof(vis));head=tail=0;ID=0;Trie *Root=new Trie();for(int i=0;i<n;i++){getchar();scanf("%s",word[i]);Insert(word[i],Root);}AC_automation(Root);getchar();scanf("%s",str);int x=query(Root);//  for(int i=0;i<n;i++)//     if(vis[i])//        printf("%s: %d\n",word[i],vis[i]);cout<<x;}return 0;}int query(Trie*root){ int i=0,cnt=0,index,len=strlen(str); Trie *p=root;  while(str[i]){  index=str[i]-'a';  while(p->next[index]==NULL && p!=root)p=p->fail; p=p->next[index]; p=(p==NULL)?root:p; Trie *temp=p; while(temp!=root && temp->count!=-1){ cnt+=temp->count;temp->count=-1; temp=temp->fail; } i++;                 }    return cnt; } 
构造失败,查询。

AC自动机其实就是解决多模式匹配的问题。

复杂度为线性,只需遍历主串。。。

例如主串为模式串为yasherhs

s->h(左下)->h(右上)

e(左下)->e(右上)

e(右上)->r

其中

{

h(左下)->h(右上)

e(左下)->e(右上)

}

是在这个模块中实现:

while(temp!=root && temp->count!=-1){ cnt+=temp->count;temp->count=-1; temp=temp->fail; }