hdu 3065(AC自动机)

病毒侵袭持续中

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19012    Accepted Submission(s): 6255

Problem Description
小t非常感谢大家帮忙解决了他的上一个问题。然而病毒侵袭持续中。在小t的不懈努力下,他发现了网路中的“万恶之源”。这是一个庞大的病毒网站,他有着好多好多的病毒,但是这个网站包含的病毒很奇怪,这些病毒的特征码很短,而且只包含“英文大写字符”。当然小t好想好想为民除害,但是小t从来不打没有准备的战争。知己知彼,百战不殆,小t首先要做的是知道这个病毒网站特征:包含多少不同的病毒,每种病毒出现了多少次。大家能再帮帮他吗?
 
Input
第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
 
Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。
 
Sample Input
3
AA
BB
CC
ooxxCC%dAAAoen....END
 
Sample Output
AA: 2
CC: 1
 
Hint
Hit: 题目描述中没有被提及的所有情况都应该进行考虑。比如两个病毒特征码可能有相互包含或者有重叠的特征码段。 计数策略也可一定程度上从Sample中推测。
 
 
AC代码1:seg=26
  1 /**
  2     Finish time:9.13.2018
  3         Author:依言
  4     Algorithm:AC_Auto
  5 */
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<map>
  9 #include<queue>
 10 #include<cstring>
 11 using namespace std;
 12 #define is_upper(x) (((x)>='A') && ((x)<='Z'))
 13 const int son=26;
 14 const int maxn=1000*50+50;
 15 
 16 char str[1010][60];
 17 struct AC_Auto
 18 {
 19     int root,L;
 20     int next[maxn][son];
 21     int fail[maxn];
 22     int id[maxn];//记录当前结束字符所表示字符串的编号
 23 
 24     void Initial()
 25     {
 26         L=0;
 27         root=L++;
 28         memset(id,0,sizeof(id));
 29         memset(next,-1,sizeof(next));
 30     }
 31     void Build_Trie(const char *s,const int num)
 32     {
 33         int now=root;
 34         while(*s != '\0')
 35         {
 36             int index=*s-'A';
 37             if(next[now][index] == -1)
 38                 next[now][index]=L++;
 39             now=next[now][index];
 40             s++;
 41         }
 42         id[now]=num;
 43     }
 44     void Build_Fail()
 45     {
 46         queue<int >myqueue;
 47         fail[root]=root;//容易忘,谨记
 48         for(int i=0;i < son;++i)
 49             if(next[root][i] == -1)
 50                 next[root][i]=root;
 51             else
 52             {
 53                 fail[next[root][i]]=root;
 54                 myqueue.push(next[root][i]);
 55             }
 56         while(!myqueue.empty())
 57         {
 58             int now=myqueue.front();
 59             myqueue.pop();
 60             for(int i=0;i < son;++i)
 61                 if(next[now][i] == -1)
 62                     next[now][i]=next[fail[now]][i];
 63                 else
 64                 {
 65                     fail[next[now][i]]=next[fail[now]][i];
 66                     myqueue.push(next[now][i]);
 67                 }
 68         }
 69     }
 70     void Query(const char *s,const int n)
 71     {
 72         int now=root;
 73         int num[1010];
 74         memset(num,0,sizeof(num));
 75         while(*s != '\0')
 76         {
 77             if(is_upper(*s))//判断当前字符知否为大写字母
 78             {
 79                 int index=*s-'A';
 80                 now=next[now][index];
 81                 int temp=now;
 82                 while(temp != root)
 83                 {
 84                     num[id[temp]]++;
 85                     temp=fail[temp];
 86                 }
 87             }
 88             else//如果不是相当于用一段新的字符串从新匹配,让now赋值为root
 89                 now=root;
 90             s++;
 91         }
 92         for(int i=1;i <= n;++i)
 93             if(num[i] != 0)
 94                 printf("%s: %d\n",str[i],num[i]);
 95     }
 96 };
 97 AC_Auto ac;
 98 char buf[2000010];
 99 int main()
100 {
101     int N;
102     while(~scanf("%d",&N))//多组输入,一下午全wa在这儿了
103     {
104         ac.Initial();
105         for(int i=1;i <= N;++i)
106         {
107             scanf("%s",str[i]);
108             ac.Build_Trie(str[i],i);
109         }
110         ac.Build_Fail();
111         scanf("%s",buf);
112         ac.Query(buf,N);
113     }
114 }
View Code

AC代码2:seg=128

  1 /**
  2     Finish time:9.13.2018
  3         Author:依言
  4     Algorithm:AC_Auto
  5 */
  6 #include<iostream>
  7 #include<queue>
  8 #include<cstdio>
  9 #include<cstring>
 10 using namespace std;
 11 const int seg=128;
 12 const int maxn=1000*50+50;
 13 
 14 int N;
 15 char str[1010][60];
 16 struct ac_auto
 17 {
 18     int root,L;
 19     int next[maxn][seg];
 20     int fail[maxn];
 21     int id[maxn];
 22     int New_Node()
 23     {
 24         for(int i=0;i < seg;++i)
 25             next[L][i]=-1;
 26         id[L]=-1;
 27         return L++;
 28     }
 29     void Initial()
 30     {
 31         L=0;
 32         root=New_Node();
 33     }
 34     void Build_Trie(const char *s,const int val)
 35     {
 36         int now=root;
 37         while(*s != '\0')
 38         {
 39             if(next[now][*s] == -1)
 40                 next[now][*s]=New_Node();
 41             now=next[now][*s];
 42             s++;
 43         }
 44         id[now]=val;//当前字符串的最后一个字符存储当前字符串的编号
 45     }
 46     void Build_Fail()
 47     {
 48         queue<int >myqueue;
 49         fail[root]=root;
 50         for(int i=0;i < seg;++i)
 51             if(next[root][i] == -1)
 52                 next[root][i]=root;
 53             else
 54             {
 55                 fail[next[root][i]]=root;
 56                 myqueue.push(next[root][i]);
 57             }
 58         while(!myqueue.empty())
 59         {
 60             int now=myqueue.front();
 61             myqueue.pop();
 62             for(int i=0;i < seg;++i)
 63                 if(next[now][i] == -1)
 64                     next[now][i]=next[fail[now]][i];
 65                 else
 66                 {
 67                     fail[next[now][i]]=next[fail[now]][i];
 68                     myqueue.push(next[now][i]);
 69                 }
 70         }
 71     }
 72     void Query(const char *s)
 73     {
 74         int num[1010];
 75         memset(num,0,sizeof(num));
 76         int now=root;
 77         while(*s != 0)
 78         {
 79             now=next[now][*s];
 80             int temp=now;
 81             while(temp != root)
 82             {
 83                 if(id[temp] != -1)
 84                     num[id[temp]]++;
 85                 temp=fail[temp];
 86             }
 87             s++;
 88         }
 89         for(int i=1;i <= N;++i)
 90             if(num[i])
 91                 printf("%s: %d\n",str[i],num[i]);
 92     }
 93 };
 94 ac_auto ac;
 95 char buf[2000010];
 96 
 97 int main()
 98 {
 99     while(~scanf("%d",&N))//多组输入,坑
100     {
101         ac.Initial();
102         for(int i=1;i <= N;++i)
103         {
104             scanf("%s",str[i]);
105             ac.Build_Trie(str[i],i);
106         }
107         ac.Build_Fail();
108         scanf("%s",buf);
109         ac.Query(buf);
110     }
111 }
View Code

AC代码3:链表

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 #define is_upper(x) (((x)>='A')&&((x)<='Z'))
  7 const int maxn=26;
  8 
  9 struct Node
 10 {
 11     Node *next[maxn];//0~~25 分别对应 a~~z || A~~Z
 12     Node *fail;
 13     int id;
 14     Node()
 15     {
 16         fail=NULL;
 17         id=0;//初始化编号为0
 18         memset(next,NULL,sizeof(next));
 19     }
 20 };
 21 int N;
 22 char str[1010][60];
 23 
 24 void Build_Tire(Node *root,const char *s,const int id)
 25 {
 26     Node *p=root;
 27     while(*s != '\0')
 28     {
 29         if(p->next[*s-'A'] == NULL)
 30             p->next[*s-'A']=new Node();
 31         p=p->next[*s-'A'];
 32         s++;
 33     }
 34     p->id=id;
 35 }
 36 void Build_fail(Node *root)
 37 {
 38     queue<Node *>myqueue;
 39     Node *p=root;
 40     root->fail=NULL;
 41     myqueue.push(root);
 42 
 43     while(!myqueue.empty())
 44     {
 45         Node *temp=myqueue.front();
 46         myqueue.pop();
 47         for(int i=0;i<maxn;i++)
 48         {
 49             if(temp->next[i] != NULL)
 50             {
 51                 if(temp == root)
 52                     temp->next[i]->fail=root;
 53                 else
 54                 {
 55                     Node *p=temp->fail;
 56                     while(p != NULL)
 57                     {
 58                         if(p->next[i] != NULL)
 59                         {
 60                             temp->next[i]->fail=p->next[i];
 61                             break;
 62                         }
 63                         p=p->fail;
 64                     }
 65                     if(p == NULL)
 66                         temp->next[i]->fail=root;
 67                 }
 68                 myqueue.push(temp->next[i]);
 69             }
 70         }
 71     }
 72 }
 73 
 74 int Query(Node *root,const char *s)
 75 {
 76     Node *p=root;
 77     int num[1010];
 78     memset(num,0,sizeof(num));
 79     while(*s != '\0')
 80     {
 81         if(!is_upper(*s))
 82         {
 83             p=root;
 84             s++;
 85             continue;
 86         }
 87         while(p->next[*s-'A'] == NULL && p != root)
 88             p=p->fail;
 89         p=p->next[*s-'A'];
 90         if(p == NULL)
 91             p=root;
 92         Node *temp=p;
 93         while(temp != root)
 94         {
 95             num[temp->id]++;
 96             temp=temp->fail;
 97         }
 98         s++;
 99     }
100     for(int i=1;i <= N;++i)
101         if(num[i])
102             printf("%s: %d\n",str[i],num[i]);
103 }
104 char buf[2000010];
105 int main()
106 {
107     while(~scanf("%d",&N))
108     {
109         Node *root=new Node();
110         for(int i=1;i <= N;++i)
111         {
112             scanf("%s",str[i]);
113             Build_Tire(root,str[i],i);
114         }
115         Build_fail(root);
116         scanf("%s",buf);
117         Query(root,buf);
118     }
119 }
View Code

 

 

posted @ 2018-09-13 16:45  HHHyacinth  阅读(193)  评论(0编辑  收藏  举报