AC自动机简单第一题hdu 2222

题目大意:

给你一些单词,给你一篇文章,需要你求出其中文章中包含了多少个单词?

例如其中的单词she、he、say、shr、her,文章yasherhs。

那么首先根据单词建立出相应的字典树。

和字典树不同的就是AC自动机要建立失败指针,实意就是为了让文章能够一次性的匹配下去。

使得某些单词的后缀能够成为某些单词的前缀,使得模式串匹配的时候不至于浪费掉了之前所匹配的次数。

 匹配之后的指针走向:

                               

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #define N 1000010
  4 char str[N];
  5 struct node
  6 {
  7        node *next[26];
  8        node *fail;
  9        int count;
 10        node()
 11        {
 12             count=0,fail=NULL;
 13             for(int i=0;i<26;i++)next[i]=NULL;
 14        }
 15 }*q[500010];
 16 int head,tail;
 17 void insert(node *root)
 18 {
 19      int i=0,index;
 20      node *p=root;
 21      while(str[i])
 22      {
 23          index=str[i]-'a';
 24          if(p->next[index]==NULL)p->next[index]=new node();
 25          p=p->next[index];
 26          i++;
 27      }
 28      p->count++;
 29 }
 30 void create_ac(node *root)
 31 {
 32      root->fail=NULL;
 33      q[head++]=root;
 34      while(head!=tail)
 35      {
 36            node *temp=q[tail++];
 37            node *p=NULL;
 38            for(int i=0;i<26;i++)
 39            {
 40                if(temp->next[i]!=NULL)
 41                {
 42                   if(temp==root)temp->next[i]->fail=root;
 43                   else
 44                   {
 45                      p=temp->fail;
 46                      while(p!=NULL)
 47                      {
 48                          if(p->next[i]!=NULL)
 49                          {
 50                             temp->next[i]->fail=p->next[i];
 51                             break;
 52                          }
 53                          p=p->fail;
 54                      }
 55                      if(p==NULL)temp->next[i]->fail=root;
 56                   }
 57                   q[head++]=temp->next[i];
 58                }
 59            }
 60       }
 61 }
 62 int query(node *root)
 63 {
 64     int answer=0,index,i=0;
 65     node *p=root;
 66     while(str[i])
 67     {
 68          index=str[i]-'a';
 69          while(p->next[index]==NULL&&p!=root)p=p->fail;
 70          p=p->next[index];
 71          p=(p==NULL)?root:p;
 72          node *temp=p;
 73          while(temp->count!=-1&&temp!=root)
 74          {
 75                answer+=temp->count;
 76                temp->count=-1;
 77                temp=temp->fail;
 78          }
 79          i++;
 80     }
 81     return answer;
 82 }
 83 int main()
 84 {
 85     int t,n;
 86     scanf("%d",&t);
 87     while(t--)
 88     {
 89           head=tail=0;
 90           scanf("%d",&n);
 91           node *root=new node();
 92           while(n--)
 93           {
 94                 scanf("%s",str);
 95                 insert(root);
 96           }
 97           create_ac(root);
 98           scanf("%s",str);
 99           printf("%d\n",query(root));
100     }
101     return 0;
102 }

 

posted @ 2013-03-01 12:47  诺小J  阅读(140)  评论(0编辑  收藏  举报