• [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数组的特性来更新,具体细节看看代码。

  • 相关阅读:
    Java基础-四要素之一《继承》
    Java基础-四要素之一《多态》
    Java基础-四大特性理解(抽象、封装、继承、多态)
    Java基础-父类-子类执行顺序
    Java基础--重写(Overriding,覆盖)-重载(Overloading)
    Java基础-数据类型转换
    Java基础-转义字符
    Java基础-数据类型int,short,char,long,float,double,boolean,byte
    算法-科学计算法
    Java基础-JVM堆与栈
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5550782.html
Copyright © 2020-2023  润新知