zoukankan      html  css  js  c++  java
  • 【模板】AC自动机

    来自洛谷的两道AC自动机模板题;

    【模板】AC自动机(简单版)

    题目背景

    这是一道简单的AC自动机模板题。

    用于检测正确性以及算法常数。

    为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交。

    管理员提示:本题数据内有重复的单词,且重复单词应该计算多次,请各位注意

    题目描述

    给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

    输入输出格式

    输入格式:

    第一行一个n,表示模式串个数;

    下面n行每行一个模式串;

    下面一行一个文本串。

    输出格式:

    一个数表示答案

    输入输出样例

    输入样例#1:
    2
    a
    aa
    aa
    输出样例#1:
    2

    说明

    subtask1[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6,n=1;

    subtask2[50pts]:∑length(模式串)<=10^6,length(文本串)<=10^6;

    代码实现

     1 #include<cstdio>
     2 const int size=1e6+10;
     3 int n,a,ans;
     4 int q[size],h,t;
     5 char ch[size],cn[size];
     6 int next[size][26],fail[size],v[size],sz;
     7 int main(){
     8     scanf("%d",&n);
     9     for(int i=1;i<=n;i++){
    10         scanf("%s",ch);
    11         for(int j=0,k=0;;j++,k=next[k][a]){
    12             if(!ch[j]){
    13                 v[k]++;
    14                 break;
    15             }
    16             a=ch[j]-'a';
    17             if(!next[k][a])next[k][a]=++sz;
    18         }
    19     }
    20     q[t++]=0;
    21     while(h<t){
    22         a=q[h++];
    23         for(int i=0,j;i<26;i++)
    24             if(next[a][i]){
    25                 j=fail[a];
    26                 while(j&&next[j][i]==0) j=fail[j];
    27                 fail[next[a][i]]=j!=a?next[j][i]:0;
    28                 q[t++]=next[a][i];
    29             }
    30     }
    31     scanf("%s",cn);
    32     for(int i=0,k=0;cn[i];i++){
    33         a=cn[i]-'a';
    34         while(k&&next[k][a]==0) k=fail[k];
    35         k=next[k][a];
    36         if(v[k]!=-1){
    37             for(int j=k;j&&v[j]!=-1;j=fail[j])
    38             ans+=v[j],v[j]=-1;
    39         }
    40     }
    41     printf("%d
    ",ans);
    42     return 0;
    43 }

    【模板】AC自动机(加强版)

    题目描述

    NNN个由小写字母组成的模式串以及一个文本串TTT。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串TTT中出现的次数最多。

    输入输出格式

    输入格式:

    输入含多组数据。

    每组数据的第一行为一个正整数NNN,表示共有NNN个模式串,1≤N≤1501 leq N leq 1501N150。

    接下去NNN行,每行一个长度小于等于707070的模式串。下一行是一个长度小于等于10610^6106​​的文本串TTT。

    输入结束标志为N=0N=0N=0。

    输出格式:

    对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。

    输入输出样例

    输入样例#1:
    2
    aba
    bab
    ababababac
    6
    beta
    alpha
    haha
    delta
    dede
    tata
    dedeltalphahahahototatalpha
    0
    输出样例#1:
    4
    aba
    2
    alpha
    haha
    代码实现
     1 #include<cstdio>
     2 #include<cstring>
     3 inline int max_(int x,int y){return x>y?x:y;}
     4 const int maxn=1<<9-1;
     5 const int maxl=1<<21-1;
     6 const int size=1<<18-1;
     7 int n,a;
     8 int q[size],h,t;
     9 int tot[maxn],ans;
    10 char ch[maxn][maxn],cn[maxl];
    11 int next[size][26],fail[size],to[size],sz;
    12 void find(int k){
    13     int i,j;
    14     for(i=to[k],j=fail[k];j;j=fail[j]) i=to[j]?to[j]:i;
    15     to[k]=i;
    16 }
    17 int main(){
    18     while(scanf("%d",&n),n){
    19         ans=sz=h=t=0;
    20         memset(to,0,sizeof(to));
    21         memset(tot,0,sizeof(tot));
    22         memset(next,0,sizeof(next));
    23         memset(fail,0,sizeof(fail));
    24         for(int i=1;i<=n;i++){
    25             scanf("%s",ch[i]);
    26             for(int j=0,k=0;;j++,k=next[k][a]){
    27                 if(!ch[i][j]){to[k]=i;break;}
    28                 a=ch[i][j]-'a';
    29                 if(!next[k][a]) next[k][a]=++sz;
    30             }
    31         }
    32         q[t++]=0;
    33         while(h<t){
    34             a=q[h++];
    35             for(int i=0,j;i<26;i++)
    36             if(next[a][i]){
    37                 j=fail[a];
    38                 while(j&&next[j][i]==0) j=fail[j];
    39                 fail[next[a][i]]=j!=a?next[j][i]:0;
    40                 q[t++]=next[a][i];
    41             }
    42         }
    43         h=0;
    44         while(h<t)
    45         find(q[h++]);
    46         scanf("%s",cn);
    47         for(int i=0,k=0;cn[i];i++){
    48             a=cn[i]-'a';
    49             while(k&&next[k][a]==0) k=fail[k];
    50             k=next[k][a];
    51             if(to[k]) ans=max_(ans,++tot[to[k]]);
    52         }
    53         printf("%d
    ",ans);
    54         for(int i=1;i<=n;i++)
    55         if(tot[i]==ans)
    56         puts(ch[i]);
    57     }
    58     return 0;
    59 }
    那个,
    2
    a
    ba
    bababa
    0
    这个自己造的数据过不了、
  • 相关阅读:
    .net中使用事务 dodo
    dnn中NULL值的处理 dodo
    通过sql server的作业调度+存储过程来实现系统定时任务的方法 dodo
    使用With...End With dodo
    ASP.NET页面中使用SolpartMenu控件 dodo
    浅解web打印 dodo
    WEB打印大全(转) dodo
    AjaxMethod未定义原因 dodo
    CommandEventArgs.CommandArgument 属性 dodo
    在用VS.NET2003 新建项目时系统提示 autometion服务器无法创建对象 这是什么问题? dodo
  • 原文地址:https://www.cnblogs.com/J-william/p/7307970.html
Copyright © 2011-2022 走看看