• [SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串


    题目链接:http://www.spoj.com/problems/LCS2/

    其实两个串的LCS会了,多个串的LCS也就差不多了。

    我们先用一个串建立后缀自动机,然后其它的串在上面跑。跑的时候算出每一个位置能往左扩展的最大长度也就是LCS。

    于是对于每一个状态维护mx数组,表示当前串与SAM在此状态的LCS值。对于一个状态取所有mx中的最小值,然后答案就是所有状态最小值中的最大值,证明显然。

    两个串的时候不用拿一个状态更新其祖先状态,但是这里需要。SAM是一个DAG图,我们通过l数组来基数排序,从叶子开始一层一层向上更新就行了。实现有点妙,具体看代码。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 char s[250010];
     6 int sz=0,la,rt,len;
     7 int l[500010],ch[500010][26],fa[500010],mn[500010];
     8 void Extend(int c){
     9     int end=++sz,tmp=la;
    10     l[end]=mn[end]=l[tmp]+1;
    11     while(tmp&&!ch[tmp][c]){
    12         ch[tmp][c]=end;
    13         tmp=fa[tmp];
    14     }
    15     if(!tmp) fa[end]=rt;
    16     else{
    17         int ne=ch[tmp][c];
    18         if(l[tmp]+1==l[ne]) fa[end]=ne;
    19         else{
    20             int np=++sz;
    21             memcpy(ch[np],ch[ne],sizeof(ch[ne]));
    22             l[np]=mn[np]=l[tmp]+1;
    23             fa[np]=fa[ne];
    24             fa[end]=fa[ne]=np;
    25             while(tmp&&ch[tmp][c]==ne){
    26                 ch[tmp][c]=np;
    27                 tmp=fa[tmp];
    28             }
    29         }
    30     }
    31     la=end;
    32 }
    33 int c[500010],a[500010];
    34 int mx[500010];
    35 void Radixsort(){
    36     for(int i=1;i<=sz;i++) c[l[i]]++;
    37     for(int i=1;i<=len;i++) c[i]+=c[i-1];
    38     for(int i=sz;i>=1;i--) a[c[l[i]]--]=i;
    39 }
    40 void Solve(){
    41     while(scanf("%s",s+1)!=EOF){
    42         int o=rt,lcs=0;
    43         for(int i=1;s[i];i++){
    44             int c=s[i]-'a';
    45             if(ch[o][c]){
    46                 o=ch[o][c];
    47                 mx[o]=max(mx[o],++lcs);
    48             }
    49             else{
    50                 while(o&&!ch[o][c]) o=fa[o];
    51                 if(!o){
    52                     o=rt;
    53                     lcs=0;
    54                 }
    55                 else{
    56                     lcs=l[o]+1;
    57                     o=ch[o][c];
    58                     mx[o]=max(mx[o],lcs);
    59                 }
    60             }
    61         }
    62         for(int i=sz;i>=1;i--){
    63             int o=a[i];
    64             mn[o]=min(mn[o],mx[o]);
    65             if(fa[o]) mx[fa[o]]=max(mx[fa[o]],mx[o]);
    66             mx[o]=0;
    67         }
    68     }
    69 }
    70 int main(){
    71     rt=la=++sz;
    72     scanf("%s",s+1);
    73     len=strlen(s+1);
    74     for(int i=1;i<=len;i++) Extend(s[i]-'a');
    75     Radixsort();
    76     Solve();
    77     int ans=0;
    78     for(int i=1;i<=sz;i++) ans=max(ans,mn[i]);
    79     printf("%d
    ",ans);
    80     return 0;
    81 }
  • 相关阅读:
    bzoj4810 [Ynoi2017]由乃的玉米田 bitset优化+暴力+莫队
    Ionic Js六:切换开关操作
    Ionic Js五:单选框操作
    Ionic Js四:复选框
    Ionic Js三:下拉刷新
    Ionic Js二:背景层
    Ionic Js一:上拉菜单(ActionSheet)
    Ionic入门十:icon(图标)
    Ionic入门九:颜色
    Ionic入门八:头部与底部
  • 原文地址:https://www.cnblogs.com/halfrot/p/7448628.html
Copyright © 2020-2023  润新知