• SPOJ1812: LCS2


    【传送门:SPOJ1811&BZOJ2946


    简要题意:

      给出若干个字符串,求出这些字符串的最长公共子串


    题解:

      后缀自动机

      这两道题的区别只是在于一道给出了字符串个数,一个没给,不过也差不多(代码就贴SPOJ的,因为数据范围大一点)

      首先用第一个字符串构造SAM

      然后处理其他的每个串在后缀自动机的每个状态能够匹配的子串最大值

      然后总的来处理所有串在这个状态能够匹配的最小值

      最后将所有状态都枚举一遍,求出其中的最大值就行了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct SAM
    {
        int son[27],fail,dep;
    }tr[210000];int root,cnt,last;
    int a[110000];
    void add(int k)
    {
        int x=a[k];
        int np=++cnt,p=last;
        tr[np].dep=k;
        while(p!=0&&tr[p].son[x]==0) tr[p].son[x]=np,p=tr[p].fail;
        if(p==0) tr[np].fail=root;
        else
        {
            int q=tr[p].son[x];
            if(tr[q].dep==tr[p].dep+1) tr[np].fail=q;
            else
            {
                int nq=++cnt;tr[nq]=tr[q];
                tr[nq].dep=tr[p].dep+1;
                tr[q].fail=tr[np].fail=nq;
                while(p!=0&&tr[p].son[x]==q) tr[p].son[x]=nq,p=tr[p].fail;
            }
        }
        last=np;
    }
    char st[110000];
    int Rsort[210000],sa[210000];
    int d[210000],f[210000];
    int main()
    {
        scanf("%s",st+1);
        int len=strlen(st+1);
        cnt=root=last=1;
        for(int i=1;i<=len;i++) a[i]=st[i]-'a'+1,add(i);
        for(int i=1;i<=cnt;i++) Rsort[tr[i].dep]++;
        for(int i=1;i<=len;i++) Rsort[i]+=Rsort[i-1];
        for(int i=cnt;i>=1;i--) sa[Rsort[tr[i].dep]--]=i;
        memset(f,63,sizeof(f));
        while(scanf("%s",st+1)!=EOF)
        {
            len=strlen(st+1);
            memset(d,0,sizeof(d));
            for(int i=1;i<=len;i++) a[i]=st[i]-'a'+1;
            int p=root,s=0,ans=0;
            for(int i=1;i<=len;i++)
            {
                if(tr[p].son[a[i]]!=0)
                {
                    s++;
                    p=tr[p].son[a[i]];
                }
                else
                {
                    while(p!=0&&tr[p].son[a[i]]==0) p=tr[p].fail;
                    if(p==0) p=root,s=0;
                    else
                    {
                        s=tr[p].dep+1,p=tr[p].son[a[i]];
                    }
                }
                d[p]=max(d[p],s);
            }
            for(int i=cnt;i>=1;i--) d[tr[sa[i]].fail]=min(tr[tr[sa[i]].fail].dep,max(d[tr[sa[i]].fail],d[sa[i]]));
            for(int i=cnt;i>=1;i--) f[sa[i]]=min(f[sa[i]],d[sa[i]]);
        }
        int ans=0;
        for(int i=1;i<=cnt;i++) ans=max(f[i],ans);
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    uva------(11464)Even Parity
    java SE学习之线程同步(详细介绍)
    MFC学习之窗口基础
    java多线程的常用方法(以及注意事项)
    java多线程下如何调用一个共同的内存单元(调用同一个对象)
    java之多线程(Thread)
    HDUOJ------3336 Count the string(kmp)
    hduoj------2594 Simpsons’ Hidden Talents
    POJ--2158--------------Milking Grid(最小覆盖字符矩阵)---(开二维kmp)
    poj-------------(2752)Seek the Name, Seek the Fame(kmp)
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8807847.html
Copyright © 2020-2023  润新知