zoukankan      html  css  js  c++  java
  • 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 != '')
     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 != '')
     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
    ",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 != '')
     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
    ",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 != '')
     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 != '')
     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
    ",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
  • 相关阅读:
    J2EE规范
    Java Web 之 SSM笔记
    Spring 官方文档笔记
    Linux学习之路--常用配置
    Linux学习之路--常用命令讲解
    人工智能学习-第二天
    人工智能学习-第一天
    人工智能学习-专业英语单词积累
    20190603 (一)安装Scrapy的环境
    20190530 数据分析
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9641526.html
Copyright © 2011-2022 走看看