zoukankan      html  css  js  c++  java
  • [Poi2000]公共串 && hustoj2797

    传送门:http://begin.lydsy.com/JudgeOnline/problem.php?id=2797

    题目大意:给你几个串求出几个串中的最长公共子串。

    题解:先看n最大才5,所以很容易想到暴力写法,因为最近在学后缀自动机就写写后缀自动机吧。

       我们将第一个串作为母串,然后在用其他的串与它进行匹配,并且记录下其匹配中每个状态的最大匹配数,答案则为每个状态的最大匹配的最小值中的最大值。。(绕晕了)

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #define N 4005
     7 using namespace std;
     8 int last,root,tot;
     9 char s[N];
    10 int n,m,ans;
    11 struct data{
    12     int son[N][26],fa[N],val[N],ans[N],sum[N],tmp[N],smin[N];
    13     void prepare(){root=last=tot=1;}
    14     int newnode(int x){val[++tot]=x; return tot;}
    15     void extend(int x)
    16     {
    17         int p=last,np=newnode(val[p]+1);
    18         for (; p && !son[p][x]; p=fa[p]) son[p][x]=np;
    19         if (!p) fa[np]=root;
    20         else
    21         {
    22             int q=son[p][x];
    23             if (val[p]+1==val[q]) fa[np]=q;
    24             else
    25             {
    26                 int nq=newnode(val[p]+1);
    27                 memcpy(son[nq],son[q],sizeof(son[q]));
    28                 fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    29                 for (; p&& son[p][x]==q; p=fa[p]) son[p][x]=nq;
    30             }
    31         }
    32         last=np;
    33     }
    34     void sort()
    35     {
    36         memset(sum,0,sizeof(sum));
    37         for (int i=1; i<=tot; i++) ans[i]=val[i];
    38         for (int i=1; i<=tot; i++) sum[val[i]]++;
    39         for (int i=1; i<=tot; i++) sum[i]+=sum[i-1];
    40         for (int i=1; i<=tot; i++) tmp[sum[val[i]]--]=i; 
    41     }
    42     void work()
    43     {
    44         scanf("%s",s+1); m=strlen(s+1);
    45         memset(smin,0,sizeof(smin));int len=0;last=root;
    46         for (int i=1; i<=m; i++)
    47         {
    48             int x=s[i]-'a';
    49             if (son[last][x]) last=son[last][x],len++;
    50             else
    51             {
    52                 for (; last&&!son[last][x];)last=fa[last];
    53                 if (!last) len=0,last=root;
    54                 else
    55                 {
    56                     len=val[last]+1; last=son[last][x];
    57                 }
    58             }
    59             smin[last]=max(smin[last],len);
    60         }
    61         for (int i=tot; i>=1; i--)
    62         {
    63             int x=tmp[i];
    64             ans[x]=min(ans[x],smin[x]);
    65             if (fa[x] && smin[x]) smin[fa[x]]=val[fa[x]];
    66         }
    67     }
    68 }SAM;
    69 int main()
    70 {
    71     scanf("%d
    ",&n); n--;
    72     SAM.prepare();
    73     scanf("%s",s+1); int len=strlen(s+1);
    74     for (int i=1; i<=len; i++) SAM.extend(s[i]-'a');
    75     SAM.sort();
    76     for (int i=1; i<=n; i++) SAM.work();
    77     for (int i=1; i<=tot; i++) ans=max(ans,SAM.ans[i]);//,cout<<i<<" "<<SAM.ans[i]<<endl;
    78     printf("%d
    ",ans);
    79 }
    View Code

    注意:我们在写的过程中,每到一个状态我们要不断跟新之前的状态答案,我们可以用dfs或者利用right数组的特性来更新,具体细节看看代码。

  • 相关阅读:
    反编译Silverlight项目
    Android 程序中像素(px)跟 单位dp(dip)之间的转换
    保存RichTextBox的文本到数据库,以及如何对RichTextBox的Document做绑定
    做事情要有五个w一个h,做项目也受用
    把RichTextBox的内容保存到数据库
    Android横竖屏切换总结
    64操作系统编译出错。The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine.
    超过连接数时强行登陆3389(远程桌面)的方法
    Android 4.0新增WiFiDirect功能
    前缀和 与 树状数组
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5550782.html
Copyright © 2011-2022 走看看