• SPOJ1811: LCS


    【传送门:SPOJ1811


    简要题意:

      给出两个字符串,求出两个字符串的最长公共子串


    题解:

      后缀自动机

      先用第一个字符串构建SAM,然后用第二个字符串去跑

      假设当前的公共子串长度为s,在SAM的状态为p,匹配到第二个字符串的第i个字符

      如果p存在连向第i个字符的边,则p=tr[p].son[st[i]-'a'+1],s++

      否则让p去跳fail直到找到存在连向第i个字符的边为止

      如果找不到,则p=root,s=0,不然p=tr[p].son[st[i]-'a'+1],s=tr[p].dep+1


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct SAM
    {
        int son[27],fail,dep;
    }tr[510000];int root,cnt,last;
    int a[310000];
    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[310000];
    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);
        scanf("%s",st+1);
        len=strlen(st+1);
        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]];
            }
            ans=max(ans,s);
        }
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    深入理解JavaScript中的this关键字
    使用yii的layout,加入<?php echo $content; ?>这句话时,它会自动在子页面上面添加一个div包裹
    使用 BEGINCONTENT() 和 ENDCONTENT() 设定 YII 的 LAYOUTS
    孙悟空的师傅是谁
    PHP MemCached高级缓存配置图文教程
    C++中的基类与派生类
    矩阵快速幂
    华为上机测试题
    2016网易研发题目
    冒泡排序
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8806660.html
Copyright © 2020-2023  润新知