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

    Longest Common Substring II

     SPOJ - 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<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100010
    using namespace std;
    char s[maxn];
    int len[maxn<<1],ch[maxn<<1][26],fa[maxn<<1],sz=1,last=1,p,q,np,nq;
    int c[maxn],sa[maxn<<1],mx[maxn<<1],ans[maxn<<1];
    void Insert(int c){
        np=++sz;
        len[np]=len[last]+1;
        ans[sz]=len[sz];
        p=last;
        while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
        if(!p)fa[np]=1;
        else {
            q=ch[p][c];
            if(len[q]==len[p]+1)fa[np]=q;
            else {
                nq=++sz;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                ans[nq]=len[nq]=len[p]+1;
                while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
            }
        }
        last=np;
    }
    void solve(){
        int l,c,now,nowlen,x;
        while(scanf("%s",s+1)!=EOF){
            l=strlen(s+1);
            now=1;nowlen=0;
            for(int i=1;i<=l;i++){
                c=s[i]-'a';
                while(now&&!ch[now][c]){
                    now=fa[now];
                    nowlen=len[now];
                }
                if(!now){
                    nowlen=0;
                    now=1;
                }
                else if(ch[now][c]){
                    nowlen++;
                    now=ch[now][c];
                }
                mx[now]=max(mx[now],nowlen);
            }
            for(int i=sz;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 Ans=0;
        for(int i=1;i<=sz;i++)Ans=max(Ans,ans[i]);
        printf("%d",Ans);
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%s",s+1);
        int l=strlen(s+1);
        for(int i=1;i<=l;i++)Insert(s[i]-'a');
        for(int i=1;i<=sz;i++)c[len[i]]++;
        for(int i=1;i<=l;i++)c[i]+=c[i-1];
        for(int i=sz;i;i--)sa[c[len[i]]--]=i;
        solve();
        return 0;
    }
  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/thmyl/p/8779164.html
Copyright © 2011-2022 走看看