• 【SPOJ】Longest Common Substring II (后缀自动机)


    【SPOJ】Longest Common Substring II (后缀自动机)

    题面

    Vjudge
    题意:求若干个串的最长公共子串

    题解

    对于某一个串构建(SAM)
    每个串依次进行匹配
    同时记录(f[i])表示走到了(i)节点
    能够匹配上的最长公共子串的长度
    当然,每个串的(f[i])可以更新(f[i.parent])
    所以需要拓扑排序

    对于每个串求出每个节点的最长匹配
    然后对他们取(min),表示某个节点大家都能匹配的最长长度
    最后对于所有点的值都取个(max)就是答案

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 120000
    struct Node
    {
        int son[26];
        int ff,len;
    }t[MAX<<1];
    char ch[MAX];
    int sum[MAX<<1],ans[MAX<<1];
    int last=1,tot=1;
    int c[MAX<<1],p[MAX<<1];
    void extend(int c)
    {
        int p=last,np=++tot;last=np;
        t[np].len=t[p].len+1;
        while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
        if(!p)t[np].ff=1;
        else
        {
            int q=t[p].son[c];
            if(t[q].len==t[p].len+1)t[np].ff=q;
            else
            {
                int nq=++tot;
                t[nq]=t[q];	
                t[nq].len=t[p].len+1;
                t[q].ff=t[np].ff=nq;
                while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
            }
        }
    }
    int main()
    {
        scanf("%s",ch+1);
        for(int i=1,l=strlen(ch+1);i<=l;++i)extend(ch[i]-97);
        for(int i=1;i<=tot;++i)c[t[i].len]++;
        for(int i=1;i<=tot;++i)c[i]+=c[i-1];
        for(int i=1;i<=tot;++i)p[c[t[i].len]--]=i;
        for(int i=1;i<=tot;++i)ans[i]=t[i].len;
        while(scanf("%s",ch+1)!=EOF)
        {
            memset(sum,0,sizeof(sum));
            for(int i=1,l=strlen(ch+1),now=1,tt=0;i<=l;++i)
            {
                int c=ch[i]-97;
                if(t[now].son[c])++tt,now=t[now].son[c];
                else
                {
                    while(now&&!t[now].son[c])now=t[now].ff;
                    if(!now)tt=0,now=1;
                    else tt=t[now].len+1,now=t[now].son[c];
                }
                sum[now]=max(sum[now],tt);
            }
            for(int i=tot;i;--i)sum[t[p[i]].ff]=max(sum[t[p[i]].ff],sum[p[i]]);
            for(int i=1;i<=tot;++i)ans[i]=min(ans[i],sum[i]);
        }
        int Ans=0;
        for(int i=1;i<=tot;++i)Ans=max(Ans,ans[i]);
        printf("%d
    ",Ans);
        return 0;
    }
    
  • 相关阅读:
    截取字符串时长度的问题
    《Asp.Net 2.0 揭秘》读书笔记(三)
    gmail的相关参数
    《Asp.Net 2.0 揭秘》读书笔记(四)
    《Asp.Net 2.0 揭秘》读书笔记(五)
    《Asp.Net 2.0 揭秘》读书笔记(一)
    今夜,我又坐在电脑面前想你
    如果你是一名经理,你必须履行经理的四项职责
    向明月买醉
    想找个人真心真意过一生
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8446374.html
Copyright © 2020-2023  润新知