zoukankan      html  css  js  c++  java
  • hdu--2896 病毒侵袭(ac自动机)

    Description

    当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋――我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~ 
    但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。 
    万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~ 

    Input

    第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。 
    接下来N行,每行表示一个病毒特征码,特征码字符串长度在20―200之间。 
    每个病毒都有一个编号,依此为1―N。 
    不同编号的病毒特征码不会相同。 
    在这之后一行,有一个整数M(1<=M<=1000),表示网站数。 
    接下来M行,每行表示一个网站源码,源码字符串长度在7000―10000之间。 
    每个网站都有一个编号,依此为1―M。 
    以上字符串中字符都是ASCII码可见字符(不包括回车)。 

    Output

    依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。 
    web 网站编号: 病毒编号 病毒编号 … 
    冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。 
    最后一行输出统计信息,如下格式 
    total: 带病毒网站数 
    冒号后有一个空格。 

    Sample Input

    3
    aaa
    bbb
    ccc
    2
    aaabbbccc
    bbaacc

    Sample Output

    web 1: 1 2 3
    total: 1
    题意:中文题意不翻译
    思路:用ac自动机去保存子串对主串进行查询,然后输出结果即可。
    心路历程:这个题可以说浪费了我大多数的时间,主要原因是模板用的不对,百度得到的链表模板几乎都进行了测试,结果大多数都是MLE。直到去学习了数组类型的模板,才避免了这个问题。不过不得不承认数组类型的模板是非常好用的。
    数组类型模板:
     1 struct trie
     2 {
     3     int next[maxn][100],fail[maxn],end[maxn];
     4     int root,L;
     5     int newnode()
     6     {
     7         for(int i=0;i<100;i++)
     8             next[L][i]=-1;
     9         end[L++]=-1;
    10         return L-1;
    11     }
    12     void init()
    13     {
    14         L=0;
    15         root=newnode();
    16     }
    17     void insert(char buf[],int id)
    18     {
    19         int len=strlen(buf);
    20         int now=root;
    21         for(int i=0;i<len;i++)
    22         {
    23             if(next[now][buf[i]-' ']==-1)
    24                 next[now][buf[i]-' ']=newnode();
    25             now=next[now][buf[i]-' '];
    26         }
    27         end[now]=id;
    28     }
    29     void build()
    30     {
    31         queue<int>Q;
    32         fail[root]=root;
    33         for(int i=0;i<100;i++)
    34             if(next[root][i]==-1)
    35             next[root][i]=root;
    36         else
    37         {
    38             fail[next[root][i]]=root;
    39             Q.push(next[root][i]);
    40         }
    41         while(!Q.empty())
    42         {
    43             int now=Q.front();
    44             Q.pop();
    45             for(int i=0;i<100;i++)
    46                 if(next[now][i]==-1)
    47                 next[now][i]=next[fail[now]][i];
    48             else
    49             {
    50                 fail[next[now][i]]=next[fail[now]][i];
    51                 Q.push(next[now][i]);
    52             }
    53         }
    54     }
    55     int query(char buf[],int id)
    56     {
    57         int res[4];
    58         bool mark[510]={0};
    59         int len=strlen(buf);
    60         int now=root;
    61         memset(res,0,sizeof(res));
    62         for(int i=0;i<len;i++)
    63         {
    64             now=next[now][buf[i]-' '];
    65             int tmp=now;
    66             while(tmp!=root)
    67             {
    68                 if(end[tmp]!=-1)
    69                 {
    70                     if(!mark[end[tmp]])
    71                     {
    72                         res[++res[0]]=end[tmp];
    73                         mark[end[tmp]]=1;
    74                     }
    75                 }
    76                 tmp=fail[tmp];
    77             }
    78         }
    79         if(res[0])
    80         {
    81             printf("web %d: ",id);
    82             sort(res+1,res+res[0]+1);
    83             for(int i=1;i<=res[0];i++)
    84             {
    85                     printf("%d%c",res[i],i==res[0]?'
    ':' ');
    86             }
    87             return 1;
    88         }
    89         return 0;
    90     }
    91 };
    View Code
    AC代码:
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <queue>
      6 #include <algorithm>
      7 using namespace std;
      8 const int maxn=200*500+5;
      9 struct trie
     10 {
     11     int next[maxn][100],fail[maxn],end[maxn];
     12     int root,L;
     13     int newnode()
     14     {
     15         for(int i=0;i<100;i++)
     16             next[L][i]=-1;
     17         end[L++]=-1;
     18         return L-1;
     19     }
     20     void init()
     21     {
     22         L=0;
     23         root=newnode();
     24     }
     25     void insert(char buf[],int id)
     26     {
     27         int len=strlen(buf);
     28         int now=root;
     29         for(int i=0;i<len;i++)
     30         {
     31             if(next[now][buf[i]-' ']==-1)
     32                 next[now][buf[i]-' ']=newnode();
     33             now=next[now][buf[i]-' '];
     34         }
     35         end[now]=id;
     36     }
     37     void build()
     38     {
     39         queue<int>Q;
     40         fail[root]=root;
     41         for(int i=0;i<100;i++)
     42             if(next[root][i]==-1)
     43             next[root][i]=root;
     44         else
     45         {
     46             fail[next[root][i]]=root;
     47             Q.push(next[root][i]);
     48         }
     49         while(!Q.empty())
     50         {
     51             int now=Q.front();
     52             Q.pop();
     53             for(int i=0;i<100;i++)
     54                 if(next[now][i]==-1)
     55                 next[now][i]=next[fail[now]][i];
     56             else
     57             {
     58                 fail[next[now][i]]=next[fail[now]][i];
     59                 Q.push(next[now][i]);
     60             }
     61         }
     62     }
     63     int query(char buf[],int id)
     64     {
     65         int res[4];
     66         bool mark[510]={0};
     67         int len=strlen(buf);
     68         int now=root;
     69         memset(res,0,sizeof(res));
     70         for(int i=0;i<len;i++)
     71         {
     72             now=next[now][buf[i]-' '];
     73             int tmp=now;
     74             while(tmp!=root)
     75             {
     76                 if(end[tmp]!=-1)
     77                 {
     78                     if(!mark[end[tmp]])
     79                     {
     80                         res[++res[0]]=end[tmp];
     81                         mark[end[tmp]]=1;
     82                     }
     83                 }
     84                 tmp=fail[tmp];
     85             }
     86         }
     87         if(res[0])
     88         {
     89             printf("web %d: ",id);
     90             sort(res+1,res+res[0]+1);
     91             for(int i=1;i<=res[0];i++)
     92             {
     93                     printf("%d%c",res[i],i==res[0]?'
    ':' ');
     94             }
     95             return 1;
     96         }
     97         return 0;
     98     }
     99 };
    100 trie ac;
    101 char buf[20005];
    102 int main()
    103 {
    104     int n,m;
    105     while(~scanf("%d",&n))
    106     {
    107         ac.init();
    108         for(int i=1;i<=n;i++)
    109         {
    110             scanf("%s",buf);
    111             ac.insert(buf,i);
    112         }
    113         ac.build();
    114         scanf("%d",&m);
    115         int total=0;
    116         for(int i=1;i<=m;i++)
    117         {
    118             scanf("%s",buf);
    119             total+=ac.query(buf,i);
    120         }
    121         printf("total: %d
    ",total);
    122     }
    123     return 0;
    124 }
    View Code

    真情推荐kuangbin大神的关于ac自动机的博客:http://www.cnblogs.com/kuangbin/category/402395.html

  • 相关阅读:
    MySQL简单实现多字段模糊查询【转】
    PHP检测URL格式是否正确域名地址是否有效【转】
    php如何判断IP为有效IP地址【转】
    PHP isset() 函数使用【转】
    php生成唯一随机码【转】
    php判断一个值是否在数组中【转】
    Win10系统gpedit.msc文件找不到,如何解决【转】
    B
    【金色】种瓜得瓜,种豆得豆 Gym
    J
  • 原文地址:https://www.cnblogs.com/wang-ya-wei/p/6091586.html
Copyright © 2011-2022 走看看