zoukankan      html  css  js  c++  java
  • SPOJ 1812 LCS2 后缀自动机

    题意:

    给10个字符串,求他们的最长公共子串。

    题解:

    只要明确后缀自动机中的每个节点都是其实都对应着逆序的后缀树的一个集合。

    而nlcs(当前最长匹配长度)和lcs都是对于这个集合而言的,所有,每个点都要更新他的*f指针(逆序后缀树的父亲)所指的节点。

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 #include <cstdio>
     6 
     7 #define N 500050
     8 
     9 using namespace std;
    10 
    11 struct SAM
    12 {
    13     SAM *son[26],*f;
    14     int l,nlcs,lcs;//当前lcs,之前所有串的lcs 
    15 }sam[N],*b[N],*head,*last;
    16 
    17 int len,ans,cnt;
    18 char str[N];
    19 int d[N];
    20 
    21 inline void add(int x)
    22 {
    23     SAM *p=&sam[++cnt],*jp=last;
    24     p->l=p->lcs=last->l+1; last=p;
    25     for(;jp&&!jp->son[x];jp=jp->f) jp->son[x]=p;
    26     if(!jp) p->f=head;
    27     else if(jp->l+1==jp->son[x]->l) p->f=jp->son[x];
    28     else
    29     {
    30         SAM *r=&sam[++cnt],*q=jp->son[x];
    31         *r=*q; r->l=r->lcs=jp->l+1;
    32         p->f=q->f=r;
    33         for(;jp&&jp->son[x]==q;jp=jp->f) jp->son[x]=r;
    34     }
    35 }
    36 
    37 inline void read()
    38 {
    39     scanf("%s",str);
    40     len=strlen(str);
    41     head=last=&sam[cnt=0];
    42     for(int i=0;i<len;i++) add(str[i]-'a');
    43 }
    44 
    45 inline void go()
    46 {
    47     for(int i=0;i<=cnt;i++) d[sam[i].l]++;
    48     for(int i=1;i<=len;i++) d[i]+=d[i-1];
    49     for(int i=0;i<=cnt;i++) b[--d[sam[i].l]]=&sam[i];
    50     while(scanf("%s",str)!=EOF)
    51     {
    52         len=strlen(str);
    53         for(int i=0;i<len;i++) str[i]-='a';
    54         int res=0; last=head;
    55         for(int i=0;i<len;i++)
    56         {
    57             if(last->son[str[i]])
    58             {
    59                 res++;
    60                 last=last->son[str[i]];
    61                 last->nlcs=max(res,last->nlcs);
    62             }
    63             else
    64             {
    65                 for(;last&&!last->son[str[i]];last=last->f);
    66                 if(!last) res=0,last=head;
    67                 else
    68                 {
    69                     res=last->l+1;
    70                     last=last->son[str[i]];
    71                     last->nlcs=max(res,last->nlcs);
    72                 }
    73             }
    74         }
    75         for(int i=cnt;i>0;i--)
    76         {
    77             b[i]->lcs=min(b[i]->nlcs,b[i]->lcs);
    78             b[i]->f->nlcs=max(b[i]->f->nlcs,b[i]->nlcs);
    79             b[i]->nlcs=0;
    80         }
    81     }
    82     ans=0;
    83     for(int i=0;i<=cnt;i++) ans=max(ans,sam[i].lcs);
    84     printf("%d\n",ans);
    85 } 
    86 
    87 int main()
    88 {
    89     read(),go();
    90     return 0;
    91 } 
  • 相关阅读:
    Xcode配置.pch文件
    iOS ViewController生命周期
    小技巧 -- 隐藏导航栏返回按钮附带的文字
    添加App启动页面
    iOS 关于nil和Nil及null与<null>的区别
    文件上传之组件
    js验证
    java mail
    validform 一款好用的表单验证插件
    tomcat启动时出错
  • 原文地址:https://www.cnblogs.com/proverbs/p/2919840.html
Copyright © 2011-2022 走看看