zoukankan      html  css  js  c++  java
  • 【hdu3065-病毒侵袭持续中】AC自动机

    http://acm.hust.edu.cn/vjudge/problem/16405

    题意:给定一些只含大写字母的病毒串,再给一个文本串,问文本串中每个病毒串各出现了多少次

    题解:

    就是用AC自动机,在每个节点末尾有个id记录是哪个单词的末尾,然后如果同时是多个单词的末尾就用一个next数组链状记录当前id的下一个值。
    多组数据坑死人。坑死人。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<queue>
      6 using namespace std;
      7 
      8 const int N=50010,S=2000010,A=26;
      9 int n,num,cnt[N],nt[N],fir[N],sum[N];
     10 char ss[N][65],s[S];
     11 queue<int> q;
     12 struct node{
     13     int id,fail,son[30];
     14 }a[N];
     15 
     16 void clear(int x)
     17 {
     18     a[x].id=a[x].fail=0;
     19     memset(a[x].son,0,sizeof(a[x].son));
     20 }
     21 
     22 void trie(char *c,int id)
     23 {
     24     int x=0,l=strlen(c);
     25     for(int i=0;i<l;i++)
     26     {
     27         int ind=c[i]-'A'+1;
     28         if(!a[x].son[ind])
     29         {
     30             num++;
     31             clear(num);
     32             a[x].son[ind]=num;
     33         }
     34         x=a[x].son[ind];
     35     }
     36     if(!a[x].id) a[x].id=id,fir[x]=id;
     37     else nt[id]=a[x].id,a[x].id=id;
     38 }
     39 
     40 void buildAC()
     41 {
     42     while(!q.empty()) q.pop();
     43     for(int i=1;i<=A;i++)
     44         if(a[0].son[i]) q.push(a[0].son[i]);
     45     while(!q.empty())
     46     {
     47         int x=q.front();q.pop();
     48         int fail=a[x].fail;
     49         for(int i=1;i<=A;i++)
     50         {
     51             if(a[x].son[i])
     52             {
     53                 int y=a[x].son[i],z=a[fail].son[i];
     54                 a[y].fail=z;                
     55                 if(fir[y]) nt[fir[y]]=a[z].id;
     56                 else a[y].id=a[z].id;
     57                 q.push(y);
     58             }
     59             else a[x].son[i]=a[fail].son[i];
     60         }
     61     }
     62 }
     63 
     64 void find(char *c)
     65 {
     66     int x=0,l=strlen(c);
     67     for(int i=0;i<l;i++)
     68     {
     69         if(!(c[i]>='A' && c[i]<='Z')) {x=0;continue;}
     70         int ind=c[i]-'A'+1;
     71         x=a[x].son[ind];
     72         int p=a[x].id;
     73         while(p)
     74         {
     75             sum[p]++;
     76             p=nt[p];
     77         }
     78     }
     79 }
     80 
     81 int main()
     82 {
     83     freopen("a.in","r",stdin);
     84     freopen("a.out","w",stdout);
     85     while(scanf("%d",&n)!=EOF)
     86     {
     87         num=0;
     88         clear(0);
     89         memset(nt,0,sizeof(nt));
     90         memset(fir,0,sizeof(fir));
     91         memset(sum,0,sizeof(sum));
     92         scanf("%d",&n);
     93         for(int i=1;i<=n;i++)
     94         {
     95             scanf("%s",ss[i]);
     96             trie(ss[i],i);
     97         }
     98         buildAC();
     99         scanf("%s",s);
    100         find(s);
    101         for(int i=1;i<=n;i++) 
    102             if(sum[i]) printf("%s: %d
    ",ss[i],sum[i]);    
    103     }
    104 
    105     return 0;
    106 }
  • 相关阅读:
    ACM训练计划
    动态规划 最长公共子序列LCS
    Floyd最短路
    邻接表拓扑排序
    数字三角形(数塔) DP入门
    hdu 5533 计算几何 判断是否为正方形
    威尔逊定理--HDU2973
    二分--POJ-3258
    01背包--hdu2639
    矩阵快速幂--51nod-1242斐波那契数列的第N项
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5686451.html
Copyright © 2011-2022 走看看