zoukankan      html  css  js  c++  java
  • 病毒侵袭 HDU

    当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到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自动机代码就完了,比起原板子题Keywords Search HDU - 2222就改了一点

    AC自动机代码详解看Keywords Search HDU - 2222

    代码:

      1 /*
      2 代码中:
      3 叶节点:代表此节点下没有子节点
      4 根节点:就是树的根
      5 子节点:就是这个节点的直接相连的节点(直系节点)
      6 
      7 此代码:
      8 用题目所给模式串构成一颗字典树
      9 然后找出来给出的待求串中每种模式串出现几次
     10 
     11 
     12 1.题目中的字符是除去回车的ASCII码可见字符(95个),我最开始定义的是以全部的ASCII码的个数(128)为基准的
     13 2.输出要排序后再输出
     14 */
     15 #include<stdio.h>
     16 #include<iostream>
     17 #include<string.h>
     18 #include<algorithm>
     19 #include<queue>
     20 using namespace std;
     21 const int maxn=30000000;
     22 typedef long long ll;
     23 int visit[maxn],length[1005];
     24 int v[1005][1005],n,m;
     25 struct Trie
     26 {
     27     int next[maxn/100][128],fail[maxn],ends[maxn];
     28     int root,L;
     29     int New_node() //创建一个新节点
     30     {
     31         for(int i=0; i<128; ++i)
     32         {
     33             next[L][i]=-1;
     34         }
     35         ends[L++]=0;
     36         return L-1;
     37     }
     38     void init()  //创建根节点
     39     {
     40         L=0;
     41         root=New_node();
     42     }
     43     void inserts(char s[],int x)  //往字典树里面插入新字符串
     44     {
     45         int len=strlen(s);
     46         int now=root;
     47         for(int i=0; i<len; ++i)
     48         {
     49             if(next[now][s[i]]==-1)
     50                 next[now][s[i]]=New_node();
     51             now=next[now][s[i]];
     52         }
     53         ends[now]=x;
     54     }
     55     void build()
     56     {
     57         queue<int>r;
     58         fail[root]=root;
     59         for(int i=0; i<128; ++i)
     60         {
     61             if(next[root][i]==-1)
     62             {
     63                 next[root][i]=root;
     64             }
     65             else
     66             {
     67                 fail[next[root][i]]=root;
     68                 r.push(next[root][i]);
     69             }
     70         }
     71         while(!r.empty())
     72         {
     73             int now=r.front();
     74             r.pop();
     75             for(int i=0; i<128; ++i)
     76             {
     77                 if(next[now][i]==-1)
     78                 {
     79                     next[now][i]=next[fail[now]][i];  //叶节点处没有设置失败节点而是往next上接了一段,这个时候
     80                     //这个fail里面的值已经在下面的else里面放过东西了
     81                 }
     82                 else
     83                 {
     84                     fail[next[now][i]]=next[fail[now]][i];  //此节点的子节点的失败节点就是此节点失败节点对应字符位置
     85                     r.push(next[now][i]);
     86                 }
     87             }
     88         }
     89     }
     90     void query(char s[],int x)
     91     {
     92         int len=strlen(s);
     93         int now=root;
     94         for(int i=0; i<len; ++i)
     95         {
     96             now=next[now][s[i]]; //这个now就保证了我们找的肯定是这个字符串中的一部分
     97             int temp=now; //这就是一直找,找到了就加1,找不到就通过失败节点看其他地方能不能找到
     98             while(temp!=root)
     99             {
    100                 if(ends[temp] && !visit[temp])
    101                 {
    102                     visit[temp]=1;
    103                     v[x][length[x]++]=ends[temp];
    104                 }
    105                 temp=fail[temp];
    106             }
    107         }
    108     }
    109 };
    110 char s[maxn];
    111 Trie ac;
    112 void init()
    113 {
    114     for(int i=0; i<=ac.L; ++i)
    115     {
    116         visit[i]=0;
    117     }
    118     for(int i=1; i<=n; ++i)
    119         length[i]=0;
    120 }
    121 
    122 int main()
    123 {
    124     scanf("%d",&n);
    125     ac.init();
    126     for(int i=1; i<=n; ++i)
    127     {
    128         scanf("%s",s);
    129         ac.inserts(s,i);
    130     }
    131     scanf("%d",&m);
    132     ac.build();
    133     int ans=0;
    134     for(int i=1; i<=m; ++i)
    135     {
    136         init();
    137         scanf("%s",s);
    138         ac.query(s,i);
    139         if(length[i])
    140         {
    141             ans++;
    142             printf("web %d: ",i);
    143             sort(v[i],v[i]+length[i]);  //之前是忘记加这个一直错,想的时候还知道要排序,写代码的时候就忘了
    144             for(int j=0; j<length[i]; ++j)
    145             {
    146                 if(j!=length[i]-1) printf("%d ",v[i][j]);
    147                 else printf("%d
    ",v[i][j]);
    148             }
    149         }
    150     }
    151     printf("total: %d
    ",ans);
    152     return 0;
    153 }
  • 相关阅读:
    WampServer软件
    ASP.NET Core中返回 json 数据首字母大小写问题
    区块链的入门与应用(1)
    阿里云oss 的坑==》 路径有区分大小写
    uni-app 学习笔记 小于号问题
    uni-app 学习笔记-引用外部js并调用
    net core 简单读取json配置文件
    net core 3 使用 autofac
    js 获取对应的url参数
    postman 跟restsharp 模拟请求http
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12029372.html
Copyright © 2011-2022 走看看