AC自动机的简单实现

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 }

 

 

 

 

你可能感兴趣的:(AC自动机)