• 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;
    }

     

  • 相关阅读:
    子类调用父类被重写的方法
    Linux下编译出现undefined reference to ‘pthread_create’问题解决
    CRC校验8
    嵌入式C语言查表法
    Static关键字,遇到的问题_1
    java中方法的参数传递机制_一个对象被当作参数传递到一个方法后
    String使用equals和==比较的区别
    如何导入XML数据 (python3.6.6区别于python2 环境)
    0xx_PHP核心01
    PHP_MVC设计模式02
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8807847.html
Copyright © 2020-2023  润新知