zoukankan      html  css  js  c++  java
  • SPOJ 1812 Longest Common Substring II

    http://www.spoj.com/problems/LCS2/

     

    题意:

    求10个串的LCS

    1、用第一个串建立后缀自动机

    2、len[s] 表示状态s 所能代表的字符串的最大长度

          mx[s] 表示状态s 在 当前匹配的串的最长匹配后缀长度

          ans[s] 表示状态s 在所有串的最长匹配后缀长度

    3、用第2——第10个串在后缀自动机上跑,每次mx[s]=max(mx[s],当前匹配长度)

          每一个串跑完之后,更新 ans[s]=min(ans[s],mx[s])

    4、每次匹配完一个字符串的时候,要 从后缀自动机 parent 树 上的叶子节点 向根更新,

       因为后缀自动机的parent树上,min[s]=max(fa[s])+1,所以子节点能匹配的长度 比 父节点的max要长。父节点是子节点的后缀,父节点可以匹配子节点的后max(fa[s])位,但是在那串在后缀自动机上跑的时候,不能保证经过 s 的 时候 也经过了s到根的链。所以只要子节点s 有匹配长度,父节点的mx[fa[s]]即可修改为len[fa[s]]即max(fa[s])

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    #define N 100002
    
    char s[N];
    
    int tot=1,len[N<<1],ch[N<<1][26],fa[N<<1];
    int last=1,p,q,np,nq;
    
    int c[N],sa[N<<1];
    
    int mx[N<<1],ans[N<<1];
    
    void extend(int c)
    {
        len[np=++tot]=len[last]+1;
        ans[tot]=len[tot];
        for(p=last;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
        if(!p) fa[np]=1;
        else
        {
            q=ch[p][c];
            if(len[q]==len[p]+1) fa[np]=q;
            else
            {
                nq=++tot;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                ans[nq]=len[nq]=len[p]+1;
                for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
            }
        }
        last=np;
    }
    
    void build()
    {
        scanf("%s",s+1);
        int L=strlen(s+1);
        for(int i=1;i<=L;++i) extend(s[i]-'a');
        for(int i=1;i<=tot;++i) c[len[i]]++;
        for(int i=1;i<=L;++i) c[i]+=c[i-1];
        for(int i=tot;i;--i) sa[c[len[i]]--]=i;
    }
    
    void solve()
    {
        int L,c,now,now_len;
        int x;
        while(scanf("%s",s+1)!=EOF)
        {
            L=strlen(s+1);
            now=1;
            now_len=0;
            for(int i=1;i<=L;++i)
            {
                c=s[i]-'a';
                while(now && !ch[now][c]) 
                {
                    now=fa[now];
                    now_len=len[now];
                }
                if(!now)
                {
                    now_len=0;
                    now=1;
                }
                else if(ch[now][c])
                {
                    now_len++;
                    now=ch[now][c];
                }
                mx[now]=max(mx[now],now_len);
            }
            for(int i=tot;i;--i)
            {
                x=sa[i];
                ans[x]=min(ans[x],mx[x]);
                if(fa[x] && mx[x]) mx[fa[x]]=len[fa[x]];
                mx[x]=0;
            }
        }
        int out=0;
        for(int i=1;i<=tot;++i) out=max(out,ans[i]);
        printf("%d",out);
    }
    
    int main()
    {
        build();
        solve();
        return 0;
    }
  • 相关阅读:
    单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件)(转)
    Android手机直播(三)声音采集
    Android 音视频去回声、降噪(Android音频采集及回音消除)(转)
    Android中Selector的setSelected“方法不管用”
    Github的快捷键
    哔哩哔哩视频显示在Github的Markdown博客页方法
    小巧的屏幕录像软件oCam
    win7各种插件的下载与使用
    3D 打印机选择说明文档
    在Ubuntu 18.04中安装Pycharm及创建Pycharm快捷方式
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8531052.html
Copyright © 2011-2022 走看看