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

    小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中推测。

    题解:

    病毒侵袭 HDU - 2896  差不多

    注意:

    1:gets读入
    2:由于目标串中匹配的时候有很多字符,但是你又不能去掉他们,但是next数组开到127的话太消耗内存,我的做法除了 'A'-'Z' 的字符之外的所有字母都变成 'Z'+1 ,这样的话只要开 next[27] 就够了。
     
      1 /*
      2 代码中:
      3 叶节点:代表此节点下没有子节点
      4 根节点:就是树的根
      5 子节点:就是这个节点的直接相连的节点(直系节点)
      6 
      7 此代码:
      8 用题目所给模式串构成一颗字典树
      9 然后找出来给出的待求串中每种模式串出现
     10 
     11 */
     12 #include<stdio.h>
     13 #include<iostream>
     14 #include<string.h>
     15 #include<algorithm>
     16 #include<queue>
     17 using namespace std;
     18 const int maxn=5e4+10;
     19 const int N=28;
     20 typedef long long ll;
     21 int v[1005];
     22 char ss[1005][55];
     23 struct Trie
     24 {
     25     int next[maxn][N],fail[maxn],ends[maxn];
     26     int root,L;
     27     int New_node() //创建一个新节点
     28     {
     29         for(int i=0; i<N; ++i)
     30         {
     31             next[L][i]=-1;
     32         }
     33         ends[L++]=0;
     34         return L-1;
     35     }
     36     void init()  //创建根节点
     37     {
     38         L=0;
     39         root=New_node();
     40     }
     41     void inserts(char s[],int x)  //往字典树里面插入新字符串
     42     {
     43         int len=strlen(s);
     44         int now=root;
     45         for(int i=0; i<len; ++i)
     46         {
     47             if(next[now][s[i]-'A']==-1)
     48                 next[now][s[i]-'A']=New_node();
     49             now=next[now][s[i]-'A'];
     50         }
     51         ends[now]=x;
     52     }
     53     void build()
     54     {
     55         queue<int>r;
     56         fail[root]=root;
     57         for(int i=0; i<N; ++i)
     58         {
     59             if(next[root][i]==-1)
     60             {
     61                 next[root][i]=root;
     62             }
     63             else
     64             {
     65                 fail[next[root][i]]=root;
     66                 r.push(next[root][i]);
     67             }
     68         }
     69         while(!r.empty())
     70         {
     71             int now=r.front();
     72             r.pop();
     73             for(int i=0; i<N; ++i)
     74             {
     75                 if(next[now][i]==-1)
     76                 {
     77                     next[now][i]=next[fail[now]][i];  //叶节点处没有设置失败节点而是往next上接了一段,这个时候
     78                     //这个fail里面的值已经在下面的else里面放过东西了
     79                 }
     80                 else
     81                 {
     82                     fail[next[now][i]]=next[fail[now]][i];  //此节点的子节点的失败节点就是此节点失败节点对应字符位置
     83                     r.push(next[now][i]);
     84                 }
     85             }
     86         }
     87     }
     88     void query(char s[])
     89     {
     90         int len=strlen(s);
     91         int now=root;
     92         //int res=0;
     93         for(int i=0; i<len; ++i)
     94         {
     95             now=next[now][s[i]-'A']; //这个now就保证了我们找的肯定是这个字符串中的一部分
     96             int temp=now; //这就是一直找,找到了就加1,找不到就通过失败节点看其他地方能不能找到
     97             while(temp!=root)
     98             {
     99                 if(ends[temp])
    100                 {
    101                     v[ends[temp]]++;
    102                 }
    103                 //res+=ends[temp];
    104                 //ends[temp]=0;
    105                 temp=fail[temp];
    106             }
    107         }
    108         //return res;
    109     }
    110 };
    111 char s[2000010];
    112 Trie ac;
    113 int main()
    114 {
    115 //    int t;
    116 //    scanf("%d",&t);
    117 //    while(t--)
    118 //    {
    119     int n;
    120     while(~scanf("%d",&n))
    121     {
    122         memset(v,0,sizeof(v));
    123         ac.init();
    124         for(int j=1; j<=n; ++j)
    125         {
    126             scanf("%s",ss[j]);
    127             int len=strlen(ss[j]);
    128             for(int i=0; i<len; ++i)
    129             {
    130                 if(ss[j][i]>'Z' || ss[j][i]<'A')
    131                 {
    132                     ss[j][i]='A'+27;
    133                 }
    134             }
    135             ac.inserts(ss[j],j);
    136         }
    137         getchar();
    138         ac.build();
    139         gets(s);
    140         int len=strlen(s);
    141         for(int i=0; i<len; ++i)
    142         {
    143             if(s[i]>'Z' || s[i]<'A')
    144             {
    145                 s[i]='A'+27;
    146             }
    147         }
    148         //printf("**
    ");
    149         ac.query(s);
    150         //printf("*");
    151         for(int i=1; i<=n; ++i)
    152         {
    153             if(v[i])
    154             {
    155                 printf("%s: %d
    ",ss[i],v[i]);
    156             }
    157         }
    158     }
    159 
    160 //   }
    161     return 0;
    162 }
  • 相关阅读:
    android监控来电显示
    android 选择本地图片并预览
    解决android http请求带中文参数会乱码(url编码)
    android连接webservice是cookies和session保持方法
    eclipse中android自动补全/提示卡机或假死
    JS中创建类得几种方式
    AJAX的简单实例应用
    JavaScript中的eval函数的用法
    JSON 入门指南
    JS中关于clientWidth、offsetWidth、scrollWidth
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12029430.html
Copyright © 2011-2022 走看看