• 【bzoj2946】[Poi2000]公共串 后缀自动机


    [Poi2000]公共串

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 1386  Solved: 620
    [Submit][Status][Discuss]

    Description

     
           给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
    任务:
    l        读入单词
    l        计算最长公共子串的长度
    l        输出结果
     

    Input

     
    文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000
     

    Output

    仅一行,一个整数,最长公共子串的长度。
     

    Sample Input

    3
    abcb
    bca
    acbc

    Sample Output

    HINT

    后缀自动机

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 
     7 #define N 2007
     8 using namespace std;
     9 inline int read()
    10 {
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 
    17 int n;
    18 char ch[N];
    19 
    20 struct SAM
    21 {
    22     int cnt,last;
    23     int fa[4005],a[4005][27],mx[4005],len[4005],ans[4005];
    24     int v[4005],q[4005];
    25     SAM(){last=++cnt;}
    26     void extend(int c)
    27     {
    28         int p=last,np=last=++cnt;mx[np]=mx[p]+1;
    29         while(!a[p][c]&&p)a[p][c]=np,p=fa[p];
    30         if(!p)fa[np]=1;
    31         else 
    32         {
    33             int q=a[p][c];
    34             if(mx[p]+1==mx[q])fa[np]=q;
    35             else 
    36             {
    37                 int nq=++cnt;mx[nq]=mx[p]+1;
    38                 memcpy(a[nq],a[q],sizeof(a[q]));
    39                 fa[nq]=fa[q];
    40                 fa[np]=fa[q]=nq;
    41                 while(a[p][c]==q)a[p][c]=nq,p=fa[p];
    42             }
    43         }
    44     }
    45     void pre()
    46     {
    47         for(int i=1;i<=cnt;i++)ans[i]=mx[i];
    48         for(int i=1;i<=cnt;i++)v[mx[i]]++;
    49         for(int i=1;i<=cnt;i++)v[i]+=v[i-1];
    50         for(int i=cnt;i;i--)q[v[mx[i]]--]=i;
    51     }
    52     void solve()
    53     {
    54         scanf("%s",ch+1);
    55         memset(len,0,sizeof(len));
    56         int l=strlen(ch+1),p=1,tmp=0;
    57         for(int i=1;i<=l;i++)
    58         {
    59             int c=ch[i]-'a';
    60             while(!a[p][c]&&p)p=fa[p];
    61             if(p==0)p=1,tmp=0;
    62             else tmp=min(tmp,mx[p])+1,p=a[p][c];
    63             len[p]=max(len[p],tmp);
    64         }
    65         for(int i=cnt;i;i--)len[fa[q[i]]]=max(len[fa[q[i]]],len[q[i]]);
    66         for(int i=1;i<=cnt;i++)ans[i]=min(ans[i],len[i]);
    67     }
    68 }sam;
    69 int main()
    70 {
    71     n=read();scanf("%s",ch+1);
    72     int l=strlen(ch+1);
    73     for(int i=1;i<=l;i++)sam.extend(ch[i]-'a');
    74     sam.pre();
    75     for(int i=1;i<n;i++)sam.solve();
    76     int ans=0;
    77     for(int i=1;i<=sam.cnt;i++)
    78         ans=max(ans,sam.ans[i]);
    79     printf("%d
    ",ans);
    80 }
  • 相关阅读:
    什么是服务网格
    RocketMQ Operator
    MySQL workbench 中文乱码 显示口口
    向mysql workbench中导入.sql文件
    怎么做一个bat文件
    SQL实践中的50句
    MYSQL中关于日期处理的函数
    计算机启动过程详解
    linux下各种软件的安装过程
    Spark配置Job History Server
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8286911.html
Copyright © 2020-2023  润新知