HDU-2222(Keywords Search)

本文深入探讨了AC自动机在关键词搜索中的应用,通过详细解释HDU2222题目解决方案,介绍了AC自动机的构建过程及查询算法,是学习AC自动机不可多得的实战指南。

还是AC自动机入门题...不解释了,可以看看其它两篇AC自动机的解题报告。

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2222

View Code
  1 //====================================================================
  2 //Name       :HDU 2222-Keywords Search
  3 //Author     :hxf
  4 //copyright  :http://www.cnblogs.com/Free-rein/
  5 //Description:
  6 //Data       :2012.7.20
  7 //========================================================================
  8 #include<iostream>
  9 #include<cmath>
 10 #include<algorithm>
 11 #include<stdio.h>
 12 #include<string.h>
 13 using namespace std;
 14 #define MAXN 10002
 15 const int len=26;//最多只有26个英文字母
 16 struct Tril{
 17     Tril *fail;
 18     Tril *son[len];
 19     int count;
 20     Tril(){
 21         fail=NULL;
 22         count=0;
 23         memset(son,NULL,sizeof(son));
 24     }
 25 }*tril[500001];
 26 char word[50];
 27 char str[1000001];
 28 void creat(char *word,Tril *root)
 29 {
 30     Tril *p=root;
 31     int lenth=strlen(word);
 32     for(int i=0;i<lenth;i++)
 33     {
 34         int index=word[i]-'a';
 35         if(p->son[index]==NULL)
 36             p->son[index]=new Tril();
 37         p=p->son[index];
 38     }
 39     p->count++;
 40 }
 41 void creat_ac_automation(Tril *root)
 42 {
 43     int first=0;
 44     int last=0;
 45     root->fail=NULL;
 46     tril[last++]=root;
 47     while(first<last)
 48     {
 49         Tril *p=tril[first++];
 50         Tril *k=NULL;
 51         for(int i=0;i<len;i++)
 52         {
 53             if(p->son[i]!=NULL)
 54             {
 55                 if(p==root)
 56                     p->son[i]->fail=root;
 57                 else
 58                 {
 59                     k=p->fail;
 60                     while(k!=NULL)
 61                     {
 62                         if(k->son[i]!=NULL)
 63                         {
 64                             p->son[i]->fail=k->son[i];
 65                             break;
 66                         }
 67                         k=k->fail;
 68                     }
 69                     if(k==NULL)
 70                     {
 71                         p->son[i]->fail=root;
 72                     }
 73                 }
 74                 tril[last++]=p->son[i];
 75             }
 76         }
 77     }
 78 }
 79 int query(Tril *root)
 80 {
 81     int lenth=strlen(str);
 82     int sum=0;
 83     Tril *p=root;
 84     for(int i=0;i<lenth;i++)
 85     {
 86         int index=str[i]-'a';
 87         while(p->son[index]==NULL&&p!=root)
 88         {
 89             p=p->fail;
 90         }
 91         p=p->son[index];
 92         if(p==NULL)
 93             p=root;
 94         Tril *k=p;
 95         while(k!=root&&k->count!=-1)
 96         {
 97             sum=sum+k->count;
 98             k->count=-1;
 99             k=k->fail;
100         }
101     }
102     return sum;
103 }
104 int main()
105 {
106     int t;
107     scanf("%d", &t);
108     while(t>0)
109     {
110         t--;
111         Tril *root=new Tril();
112         int n;
113         scanf("%d", &n);
114         for(int i = 0;i < n;i++)
115         {
116             scanf("%s", word);
117             getchar();
118             creat(word,root);
119         }
120         creat_ac_automation(root);
121         scanf("%s",str);
122         getchar();
123         printf("%d\n",query(root));
124     }
125     return 0;
126 }

 

 

转载于:https://www.cnblogs.com/Free-rein/archive/2012/08/09/2630206.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值