• 【BZOJ 2946】 2946: [Poi2000]公共串 (SAM)


    2946: [Poi2000]公共串

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 1063  Solved: 469

    Description

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

    Input

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

    Output

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

    Sample Input

    3
    abcb
    bca
    acbc

    Sample Output

    HINT

    Source

    【分析】

      重新学一次SAM,从刷水题开始。

      同spoj1812。用第一个串建sam,然后用其他的串跑,ans存在那个点那里,做完一个串的时候还要根据parent边的拓扑序更新该点ans,最后取min即可。

      当然后缀数组也是可以的。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 2010
     8 
     9 int mymax(int x,int y) {return x>y?x:y;}
    10 int mymin(int x,int y) {return x<y?x:y;}
    11 
    12 struct node
    13 {
    14     int pre,son[30],step;
    15     // node() {pre=step=0;memset(son,0,sizeof(son));}
    16 }t[Maxn*2];
    17 int ans[Maxn*2],ad[Maxn*2];
    18 
    19 struct sam
    20 {
    21     int last,tot;
    22     /*void upd(int x)
    23     {
    24         memset(t[x].son,0,sizeof(t[x].son));
    25     }*/
    26     void extend(int k)
    27     {
    28         int np=++tot,p=last;
    29         t[np].step=t[last].step+1;
    30         while(p&&!t[p].son[k])
    31         {
    32             t[p].son[k]=np;
    33             p=t[p].pre;
    34         }
    35         if(!p) t[np].pre=1;
    36         else
    37         {
    38             int q=t[p].son[k];
    39             if(t[q].step==t[p].step+1) t[np].pre=q;
    40             else
    41             {
    42                 int nq=++tot;//upd(tot);
    43                 t[nq].step=t[p].step+1;
    44                 memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
    45                 t[nq].pre=t[q].pre;
    46                 t[q].pre=t[np].pre=nq;
    47                 while(p&&t[p].son[k]==q)
    48                 {
    49                     t[p].son[k]=nq;
    50                     p=t[p].pre;
    51                 }
    52             }
    53         }
    54         last=np;
    55     }
    56     
    57 }sam;
    58 
    59 char s[10],ss[Maxn];
    60 
    61 int main()
    62 {
    63     int n;scanf("%d",&n);
    64     scanf("%s",s);
    65     sam.last=sam.tot=1;
    66     int l=strlen(s);
    67     for(int i=0;i<l;i++) sam.extend(s[i]-'a'+1);
    68     memset(ans,63,sizeof(ans));
    69     for(int i=2;i<=n;i++)
    70     {
    71         scanf("%s",s);
    72         l=strlen(s);
    73         int nw=1,sp=0;
    74         for(int j=1;j<=sam.tot;j++) ad[j]=0;
    75         for(int j=0;j<l;j++)
    76         {
    77             int ind=s[j]-'a'+1;
    78             while(nw&&!t[nw].son[ind]) nw=t[nw].pre,sp=t[nw].step;
    79             if(t[nw].son[ind]) sp++,nw=t[nw].son[ind];
    80             else nw=1,sp=0;
    81             ad[nw]=mymax(ad[nw],sp);
    82         }
    83         for(int i=sam.tot;i>=1;i--) ad[t[i].pre]=mymax(ad[t[i].pre],mymin(ad[i],t[t[i].pre].step));
    84         for(int i=sam.tot;i>=1;i--) ans[i]=mymin(ans[i],ad[i]);
    85     }
    86     int mx=0;
    87     for(int i=1;i<=sam.tot;i++) if(ans[i]<=sam.tot) mx=mymax(mx,ans[i]);
    88     printf("%d
    ",mx);
    89     return 0;
    90 }
    View Code

    2017-04-17 10:21:42

  • 相关阅读:
    Spring Annotation注解进行aop的学习
    使用ADO读取SQL数据库
    GetInventTable组装SQL语句使用通配符
    获取当前用户所属的所有仓位,DictRelation,
    UnitConvert,单位换算,单位转换
    数字货币书写转英文货币书写
    导出xml
    存储过程IN参数疑难问题解决方法
    TempTable 临时表
    多栏报表 多列报表
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6721616.html
Copyright © 2020-2023  润新知