hdu-3065-AC自动机

http://acm.hdu.edu.cn/showproblem.php?pid=3065

病毒侵袭持续中

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16495    Accepted Submission(s): 5577


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

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  2243 2825 3247 3341 2296 
 
 
   利用AC自动机统计病毒出现的次数并输出就好了,模板题;多组输入比较坑,,看题以为是单组坑我好久。
 
复制代码
  1 #include<bits/stdc++.h>
  2 using namespace  std;
  3 char str[2000005];
  4 char ma[1010][51];
  5 int times[1010];
  6 struct aho
  7 {
  8     int next[50005][26];
  9     int fail[50005];
 10     int can[50005];
 11     int tot;
 12 
 13     int idx(char c){return c-'A';}
 14 
 15     void init()
 16     {
 17         memset(times,0,sizeof(times));
 18         memset(can,0,sizeof(can));
 19         memset(fail,-1,sizeof(fail));
 20         memset(next,-1,sizeof(next));
 21         tot=1;
 22     }
 23 
 24     void insert(char *S,int k)
 25     {
 26         int now=0,n=strlen(S);
 27         for(int i=0;i<n;++i){
 28             int c=idx(S[i]);
 29             if(next[now][c]==-1) next[now][c]=tot++;
 30             now=next[now][c];
 31         }
 32         can[now]=k;
 33     }
 34 
 35     void build_fail()
 36     {
 37         queue<int>q;
 38         q.push(0);
 39         while(!q.empty()){
 40             int u=q.front();q.pop();
 41             for(int i=0;i<26;++i){
 42                 int v=next[u][i];
 43                 if(v==-1) continue;
 44                 int t=fail[u];
 45                 while(t!=-1&&next[t][i]==-1)t=fail[t];
 46                 if(t!=-1){
 47                     fail[next[u][i]]=next[t][i];
 48                 }
 49                 else fail[next[u][i]]=0;
 50                 q.push(next[u][i]);
 51             }
 52         }
 53     }
 54 
 55     void go(int u)
 56     {
 57         while(u!=-1){
 58             if(can[u])times[can[u]]++;
 59             u=fail[u];
 60         }
 61     }
 62 
 63     void solve()
 64     {
 65         int n=strlen(str),now=0;
 66         for(int i=0;i<n;++i){
 67             int c=idx(str[i]);
 68             if(c>=0&&c<26){
 69             if(next[now][c]!=-1){
 70                 now=next[now][c];
 71             }
 72             else{
 73                 int v=fail[now];
 74                 while(v!=-1&&next[v][c]==-1)v=fail[v];
 75                 if(v!=-1){
 76                     now=next[v][c];
 77                 }
 78                 else{
 79                     now=0;
 80                 }
 81             }
 82             }
 83             else{
 84                 now=0;
 85             }
 86             if(can[now]!=-1){
 87                 go(now);
 88             }
 89         }
 90     }
 91 }a;
 92 int main()
 93 {
 94     int n,i,j,k;
 95     while(cin>>n){a.init();
 96     for(i=1;i<=n;++i){
 97         scanf("%s",ma[i]);
 98         a.insert(ma[i],i);
 99     }
100     scanf("%s",str);
101     a.build_fail();
102     a.solve();
103     for(i=1;i<=n;++i)
104     {
105         if(times[i]){
106             printf("%s: %d\n",ma[i],times[i]);
107         }
108     }
109     }
110     return 0;
111 }
复制代码

 

 
posted @   *zzq  阅读(273)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示