zoukankan      html  css  js  c++  java
  • HDU 3065 病毒侵袭持续中(AC自动机)

    小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 #include<cstring>
      2 #include <cmath>
      3 #include <iostream>
      4 #include<queue>
      5 #include<cstdio>
      6 #include<map>
      7 #include<string>
      8 using namespace std;
      9 const int SIGMA_SIZE = 128;
     10 const int MAXNODE = 500005;
     11 int n, m, X, Y;
     12 char p[1010][51];
     13  
     14 struct ACautomata  {
     15     int ch[MAXNODE][SIGMA_SIZE];
     16     int f[MAXNODE];    
     17     int val[MAXNODE];  
     18     int last[MAXNODE]; 
     19     int cnt[2000];
     20     int sz;
     21     int tot_web;
     22     void init() 
     23     {
     24         sz = 1;
     25         memset(ch[0], 0, sizeof(ch[0]));
     26         memset(val, 0, sizeof(val));
     27         memset(cnt, 0, sizeof(cnt));
     28         tot_web=0;
     29     }
     30  
     31     
     32     int idx(char c) {  return (int)c; }  
     33  
     34     void insert(char *s,int v) 
     35     {
     36         int now = 0,len=strlen(s);
     37         for(int i = 0; i < len; i++) 
     38         {
     39             int c = idx(s[i]);
     40             if(!ch[now][c]) 
     41             {
     42                 memset(ch[sz], 0, sizeof(ch[sz]));
     43                 val[sz] = 0;
     44                 ch[now][c] = sz++;
     45             }
     46             now = ch[now][c];
     47         }
     48         val[now] = v;
     49     }
     50  
     51     void print(int j) 
     52     {
     53         if(j) 
     54         {
     55             ++cnt[val[j]];
     56             print(last[j]);
     57         }
     58     }
     59     
     60     void find(char *text) 
     61     {
     62         int j = 0,len=strlen(text); 
     63         for(int i = 0; i < len; i++) 
     64         { 
     65             int c = idx(text[i]);
     66             j = ch[j][c];
     67             if(val[j])     print(j);
     68             else if(last[j]) print(last[j]); 
     69         }
     70     }
     71     
     72     void get_fail()
     73     {
     74         queue<int> q; f[0] = 0;
     75         for (int c = 0; c < SIGMA_SIZE; c++)
     76         {
     77             int r = ch[0][c];
     78             if (r)
     79             {
     80                 f[r]=0;
     81                 q.push(r);
     82                 last[r] = 0;
     83             }
     84         }
     85         while (!q.empty())
     86         {
     87             int u = q.front(); q.pop();
     88             for (int c = 0; c < SIGMA_SIZE; ++ c)
     89             {
     90                 int r = ch[u][c];    
     91                 if (!r)    
     92                 {
     93                     ch[u][c] = ch[f[u]][c];
     94                     continue;
     95                 }
     96                 q.push(r);        
     97                 int pre = f[u];    
     98                 while (pre && !ch[pre][c])    pre = f[pre];
     99                 f[r] = ch[pre][c];
    100                 last[r] = val[f[r]] ? f[r] : last[f[r]];
    101             }
    102         }
    103     }
    104  
    105 } ac;
    106 char text[2000010]; 
    107 int main() 
    108 {
    109  
    110     while (~scanf("%d", &n))
    111     {
    112         ac.init();
    113         for (int i = 1; i <= n; ++ i)    
    114         {
    115             scanf("%s", p[i]);
    116             ac.insert(p[i],i);
    117         }
    118         ac.get_fail();
    119         scanf("%s", text);
    120         ac.find(text);
    121         for (int i = 1;i <= n;++i) if(ac.cnt[i]) printf("%s: %d
    ", p[i], ac.cnt[i]);
    122         
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    二叉搜索树的java实现
    HashMap源码分析
    集合之LinkedList源码分析
    集合之ArrayList的源码分析
    CountDownLatch源码解析
    部署java项目到阿里云服务器(centos7版本)
    并发中的单例模式
    AbstractQueuedSynchronizer的简单分析
    ThreadPoolExecutor的分析(二)
    ThinkPHP5 与 ThinkPHP3.* 之间的使用差异
  • 原文地址:https://www.cnblogs.com/csushl/p/9483781.html
Copyright © 2011-2022 走看看