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
    这个自己造的数据过不了、
  • 相关阅读:
    UVA 10600 ACM Contest and Blackout(次小生成树)
    UVA 10369
    UVA Live 6437 Power Plant 最小生成树
    UVA 1151 Buy or Build MST(最小生成树)
    UVA 1395 Slim Span 最小生成树
    POJ 1679 The Unique MST 次小生成树
    POJ 1789 Truck History 最小生成树
    POJ 1258 Agri-Net 最小生成树
    ubuntu 用法
    ubuntu 搭建ftp服务器,可以通过浏览器访问,filezilla上传文件等功能
  • 原文地址:https://www.cnblogs.com/J-william/p/7307970.html
Copyright © 2011-2022 走看看