HDU-2896(病毒侵袭)

      还是AC自动机模板题,和上题差不多,只不过此题需要鉴定不止一条字符串,具体做法是一样的,不懂AC自动机的同学可以去百度google一下AC自动机,总之就是用来匹配多个字符串的一种算法,具体步骤是:建立tril树---寻找失败节点(creat_ac_automation这个函数)---遍历字符串就OK了,模板题就不多解释了,不懂可以留言。

题目地址是:http://acm.hdu.edu.cn/showproblem.php?pid=2896
View Code
  1 //====================================================================
  2 //Name       :
  3 //Author     :hxf
  4 //copyright  :http://www.cnblogs.com/Free-rein/
  5 //Description:
  6 //Data       :2012.8.5
  7 //========================================================================
  8 #include<iostream>
  9 #include<algorithm>
 10 #include<stdio.h>
 11 #include<math.h>
 12 #include<string.h>
 13 #include <vector>
 14 #include <stack>
 15 #define MAX 100005
 16 #define inf 1499999999
 17 using namespace std;
 18 const int len=130;
 19 struct Tril{
 20     Tril *fail;
 21     Tril *son[len];
 22     int count;
 23     int num;
 24     Tril(){
 25         fail=NULL;
 26         count=0;
 27         num=0;
 28         memset(son,NULL,sizeof(son));
 29     }
 30 }*tril[1000050];
 31 char virus[1050];
 32 int total;
 33 int n;
 34 char str[100050];
 35 void creat(char* virus,Tril* root,int k)
 36 {
 37     Tril *p=root;
 38     int lenth=strlen(virus);
 39     for(int i=0;i<lenth;i++)
 40     {
 41         int index=virus[i];
 42         if(p->son[index]==NULL)
 43             p->son[index]=new Tril();
 44         p=p->son[index];
 45     }
 46     p->count++;
 47     p->num=k;
 48 }
 49 void creat_ac_automation(Tril *root)
 50 {
 51     int first=0;
 52     int last=0;
 53     root->fail=NULL;
 54     tril[last++]=root;
 55     while(first<last)
 56     {
 57         Tril *p=tril[first++];
 58         Tril *k=NULL;
 59         for(int i=0;i<len;i++)
 60         {
 61             if(p->son[i]!=NULL)
 62             {
 63                 if(p==root)
 64                     p->son[i]->fail=root;
 65                 else
 66                 {
 67                     k=p->fail;
 68                     while(k!=NULL)
 69                     {
 70                         if(k->son[i]!=NULL)
 71                         {
 72                             p->son[i]->fail=k->son[i];
 73                             break;
 74                         }
 75                         k=k->fail;
 76                     }
 77                     if(k==NULL)
 78                     {
 79                         p->son[i]->fail=root;
 80                     }
 81                 }
 82                 tril[last++]=p->son[i];
 83             }
 84         }
 85     }
 86 }
 87 int query(Tril* root,int temp)
 88 {
 89     int vir[1005];
 90     int visit[1005];
 91     memset(visit,0,sizeof(visit));
 92     int viru=0;
 93     int lenth=strlen(str);
 94     int s=-1;
 95     Tril* p=root;
 96     for(int i=0;i<lenth;i++)
 97     {
 98         int index=str[i];
 99         while(p->son[index]==NULL&&p!=root)
100             p=p->fail;
101         p=p->son[index];
102         if(p==NULL)
103             p=root;
104         Tril *k=p;
105         while(k!=root)
106         {
107             if(s==-1&&k->num>0)
108             {
109                 printf("web %d:",temp);
110                 s=0;
111             }
112             if(k->num>0&&visit[k->num]==0)
113             {
114                 vir[viru++]=k->num;
115                 visit[k->num]=1;
116             }
117             k=k->fail;
118         }
119     }
120     sort(vir,vir+viru);
121     for(int i=0;i<viru;i++)
122         printf(" %d",vir[i]);
123     if(s==0)
124     {
125         printf("\n");
126         return 1;
127     }
128     else
129         return -1;
130 }
131 
132 int main()
133 {
134     Tril* root=new Tril();
135     scanf("%d",&n);
136     for(int i=0;i<n;i++)
137     {
138         scanf("%s",virus);
139         getchar();
140         creat(virus,root,i+1);
141     }
142     creat_ac_automation(root);
143     int m;
144     scanf("%d",&m);
145     total=0;
146     for(int i=0;i<m;i++)
147     {
148         scanf("%s",str);
149         getchar();
150         if(query(root,i+1)==1)
151             total++;
152     }
153     printf("total: %d\n",total);
154     return 0;
155 }

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值