zoukankan      html  css  js  c++  java
  • ac自动机小结

    关于ac自动机模板是非常重要的,在上一篇文章中已经给出了非常好用的数组类型的模板。下面的题目都是在模板之上进行略微修改就能ac的简单题

    1.hdu--3065 病毒侵袭持续中 

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

    题意:统计子串在主串中出现的次数,分别打印出来

    思路:由于都是大写字母所以next[][26]即可,非大写字母在查询时跳过就行。模板本身就能对字符串进行统计,所以用一个新的数组记录结果就行。

    AC代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <queue>
      6 #include <algorithm>
      7 using namespace std;
      8 const int maxn=1005*55+5;
      9 int res[1005];
     10 char buf[1005][55];
     11 struct trie
     12 {
     13     int next[maxn][128],fail[maxn],end[maxn];
     14     int root,L;
     15     int newnode()
     16     {
     17         for(int i=0; i<128; i++)
     18             next[L][i]=-1;
     19         end[L++]=-1;
     20         return L-1;
     21     }
     22     void init()
     23     {
     24         L=0;
     25         root=newnode();
     26     }
     27     void insert(char buf[],int id)
     28     {
     29         int len=strlen(buf);
     30         int now=root;
     31         for(int i=0; i<len; i++)
     32         {
     33             if(next[now][buf[i]]==-1)
     34                 next[now][buf[i]]=newnode();
     35             now=next[now][buf[i]];
     36         }
     37         end[now]=id;
     38     }
     39     void build()
     40     {
     41         queue<int>Q;
     42         fail[root]=root;
     43         for(int i=0; i<128; i++)
     44             if(next[root][i]==-1)
     45                 next[root][i]=root;
     46             else
     47             {
     48                 fail[next[root][i]]=root;
     49                 Q.push(next[root][i]);
     50             }
     51         while(!Q.empty())
     52         {
     53             int now=Q.front();
     54             Q.pop();
     55             for(int i=0; i<128; i++)
     56                 if(next[now][i]==-1)
     57                     next[now][i]=next[fail[now]][i];
     58                 else
     59                 {
     60                     fail[next[now][i]]=next[fail[now]][i];
     61                     Q.push(next[now][i]);
     62                 }
     63         }
     64     }
     65     int query(char buf[])
     66     {
     67         int len=strlen(buf);
     68         int now=root;
     69         memset(res,0,sizeof(res));
     70         for(int i=0; i<len; i++)
     71         {
     72             now=next[now][buf[i]];
     73             int tmp=now;
     74             while(tmp!=root)
     75             {
     76                 if(end[tmp]!=-1)
     77                 {
     78                     res[end[tmp]]++;
     79                 }
     80                 tmp=fail[tmp];
     81             }
     82         }
     83         return 0;
     84     }
     85 };
     86 trie ac;
     87 char str[2000005];
     88 int main()
     89 {
     90     int n,m;
     91     while(~scanf("%d",&n))
     92     {
     93         ac.init();
     94         getchar();
     95         for(int i=1; i<=n; i++)
     96         {
     97             scanf("%s",buf[i]);
     98             ac.insert(buf[i],i);
     99         }
    100         ac.build();
    101         scanf("%s",str);
    102         ac.query(str);
    103         for(int i=1; i<=n; i++)
    104             if(res[i])
    105                 printf("%s: %d
    ",buf[i],res[i]);
    106     }
    107     return 0;
    108 }
    View Code

    2.hdu--5384 Danganronpa 

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

    题意:先给n个主串,再给m个子串,求每个主串中每个子串出现的次数。

    思路:由于数据的原因用二维数组存放主串是不合适的,因此有三个一维数组去记录数据,问题就变得非常的简单了。还有就是string类型转成char类型的函数str.c.str()在编译器中会出错不然的话有此函数也是一种方法。

    AC代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <queue>
      6 #include <algorithm>
      7 using namespace std;
      8 const int maxn=600000+5;
      9 struct trie
     10 {
     11     int next[maxn][26],fail[maxn],end[maxn];
     12     int root,L;
     13     int newnode()
     14     {
     15         for(int i=0; i<26; i++)
     16             next[L][i]=-1;
     17         end[L++]=0;
     18         return L-1;
     19     }
     20     void init()
     21     {
     22         L=0;
     23         root=newnode();
     24     }
     25     void insert(char buf[],int id)
     26     {
     27         int len=strlen(buf);
     28         int now=root;
     29         for(int i=0; i<len; i++)
     30         {
     31             if(next[now][buf[i]-'a']==-1)
     32                 next[now][buf[i]-'a']=newnode();
     33             now=next[now][buf[i]-'a'];
     34         }
     35         end[now]++;
     36     }
     37     void build()
     38     {
     39         queue<int>Q;
     40         fail[root]=root;
     41         for(int i=0; i<26; i++)
     42             if(next[root][i]==-1)
     43                 next[root][i]=root;
     44             else
     45             {
     46                 fail[next[root][i]]=root;
     47                 Q.push(next[root][i]);
     48             }
     49         while(!Q.empty())
     50         {
     51             int now=Q.front();
     52             Q.pop();
     53             for(int i=0; i<26; i++)
     54                 if(next[now][i]==-1)
     55                     next[now][i]=next[fail[now]][i];
     56                 else
     57                 {
     58                     fail[next[now][i]]=next[fail[now]][i];
     59                     Q.push(next[now][i]);
     60                 }
     61         }
     62     }
     63     int query(char buf[],int n,int m)
     64     {
     65         int len=strlen(buf);
     66         int now=root,cnt=0;
     67         for(int i=n; i<m; i++)
     68         {
     69             now=next[now][buf[i]-'a'];
     70             int tmp=now;
     71             while(tmp!=root)
     72             {
     73                 if(end[tmp]!=-1)
     74                 {
     75                     cnt+=end[tmp];
     76                 }
     77                 tmp=fail[tmp];
     78             }
     79         }
     80         return cnt;
     81     }
     82 };
     83 trie ac;
     84 char str[6000005];
     85 int a[100005],b[1000005];
     86 char buf[10005];
     87 int main()
     88 {
     89     int n,m,t,la;
     90     while(~scanf("%d",&t))
     91     {
     92         while(t--)
     93         {
     94             ac.init();
     95             scanf("%d%d",&n,&m);
     96             getchar();
     97             la=0;
     98             for(int i=1; i<=n; i++)
     99             {
    100                 scanf("%s",buf);
    101                 strcpy(str+la,buf);
    102                 a[i]=la;
    103                 la=strlen(buf)+la;
    104                 b[i]=la;
    105             }
    106             for(int i=1; i<=m; i++)
    107             {
    108                 scanf("%s",buf);
    109                 ac.insert(buf,i);
    110             }
    111             ac.build();
    112             for(int i=1; i<=n; i++)
    113             {
    114                 printf("%d
    ",ac.query(str,a[i],b[i]));
    115             }
    116         }
    117     }
    118     return 0;
    119 }
    View Code

    3.hdu--5880  Family View

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

    题意:先给出m个子串(只有小写字母),再给出一个主串,如果主串包含子串则把包含部分变成 * 

    思路:用数组dis[]储存子串长度,当主串包含子串时,就把当前字符之前的dis[k]个字符变成 * 。由于主串大小写通用,所以大写时 -‘A’、小写时 -‘a’,否则跳过就行了。

    AC代码:

      1 #include <iostream>
      2 #include<cstdio>
      3 #include <cstring>
      4 #include <queue>
      5 using namespace std;
      6 const int maxn=1000005;
      7 char str[1000005];
      8 struct trie
      9 {
     10     int next[maxn][26],fail[maxn],end[maxn],dis[maxn];
     11     int root,L;
     12     int newnode()
     13     {
     14         for(int i=0; i<26; i++)
     15             next[L][i]=-1;
     16         end[L++]=-1;
     17         dis[maxn]=0;
     18         return L-1;
     19     }
     20     void init()
     21     {
     22         L=0;
     23         root=newnode();
     24     }
     25     void insert(char buf[],int id)
     26     {
     27         int len=strlen(buf);
     28         int now=root;
     29         for(int i=0; i<len; i++)
     30         {
     31             if(next[now][buf[i]-'a']==-1)
     32                 next[now][buf[i]-'a']=newnode();
     33             now=next[now][buf[i]-'a'];
     34         }
     35         end[now]=id;
     36         dis[now]=len;
     37     }
     38     void build()
     39     {
     40         queue<int>Q;
     41         fail[root]=root;
     42         for(int i=0; i<26; i++)
     43             if(next[root][i]==-1)
     44                 next[root][i]=root;
     45             else
     46             {
     47                 fail[next[root][i]]=root;
     48                 Q.push(next[root][i]);
     49             }
     50         while(!Q.empty())
     51         {
     52             int now=Q.front();
     53             Q.pop();
     54             for(int i=0; i<26; i++)
     55                 if(next[now][i]==-1)
     56                     next[now][i]=next[fail[now]][i];
     57                 else
     58                 {
     59                     fail[next[now][i]]=next[fail[now]][i];
     60                     Q.push(next[now][i]);
     61                 }
     62         }
     63     }
     64     int query()
     65     {
     66         int len=strlen(str);
     67         int now=root;
     68         for(int i=0; i<len; i++)
     69         {
     70             if(str[i]>='a'&&str[i]<='z')
     71             now=next[now][str[i]-'a'];
     72             else if(str[i]>='A'&&str[i]<='Z')
     73                 now=next[now][str[i]-'A'];
     74             else
     75                 continue;
     76             int tmp=now;
     77             while(tmp!=root)
     78             {
     79                 if(end[tmp]!=-1)
     80                 {
     81                     int cnt=dis[tmp],j=i;
     82                     while(cnt--)
     83                     {
     84                         str[j--]='*';
     85                     }
     86                 }
     87                 tmp=fail[tmp];
     88             }
     89         }
     90         return 0;
     91     }
     92 };
     93 trie ac;
     94 int main()
     95 {
     96     int t,m;
     97     while(~scanf("%d",&t))
     98     {
     99         while(t--)
    100         {
    101             ac.init();
    102             scanf("%d",&m);
    103             getchar();
    104             for(int i=1;i<=m;i++)
    105             {
    106                 gets(str);
    107                 ac.insert(str,i);
    108             }
    109             ac.build();
    110             gets(str);
    111             ac.query();
    112             puts(str);
    113         }
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    js对select动态添加和删除OPTION
    文本框textarea实时提示还可以输入多少文字
    JavaScript中统计Textarea字数并提示还能输入的字符
    inupt textarea提示文字(点击消失,不输入恢复)
    inupt textarea提示文字(点击消失,不输入恢复)及限制字数
    Server.MapPath()获取本机绝对路径
    cocos基础教程(12)点击交互的三种处理
    cocos基础教程(9)声音和音效
    cocos进阶教程(2)多分辨率支持策略和原理
    cocos基础教程(10)纹理缓存技术
  • 原文地址:https://www.cnblogs.com/wang-ya-wei/p/6091698.html
Copyright © 2011-2022 走看看