• spoj1812-Longest Common Substring II(后缀自动机)


    Description

    A string is finite sequence of characters over a non-empty finite set Σ.

    In this problem, Σ is the set of lowercase letters.

    Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

    Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

    Here common substring means a substring of two or more strings.

    Input

    The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

    Output

    The length of the longest common substring. If such string doesn't exist, print "0" instead.

    Example

    Input:
    alsdfkjfjkdsal
    fdjskalajfkdsla
    aaaajfaaaa
    
    Output:
    2

    题意:给若干个字符串,长度不超过100000,求最长公共连续字串
    解析:后缀自动机,对输入的第一个字符串建一个后缀自动机,在
    sam中添加两个量Max[i](查询时以第i个节点为最后一个字符的后缀的最大长度)
    ,Min[i](所有查询Max[i]中的最小值)。

    代码

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int maxn=200005;
    struct SAM
    {
        int ch[maxn][26];
        int pre[maxn],step[maxn];
        int last,id;
        int Min[maxn],Max[maxn];
        void init() //初始化
        {
            last=id=0;
            memset(ch[0],-1,sizeof(ch[0]));
            pre[0]=-1; step[0]=0;
            Min[0]=Max[0]=0;
        }
        void Insert(int c) //模板,自己百度
        {
            int p=last,np=++id;
            step[np]=step[p]+1;
            memset(ch[np],-1,sizeof(ch[np]));
            Min[np]=Max[np]=step[np];
            while(p!=-1&&ch[p][c]==-1)  ch[p][c]=np,p=pre[p];
            if(p==-1) pre[np]=0;
            else
            {
                int q=ch[p][c];
                if(step[q]!=step[p]+1)
                {
                    int nq=++id;
                    memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    step[nq]=step[p]+1;
                    Min[nq]=Max[nq]=step[nq];
                    pre[nq]=pre[q];
                    pre[np]=pre[q]=nq;
                    while(p!=-1&&ch[p][c]==q) ch[p][c]=nq,p=pre[p];
                }
                else pre[np]=q;
            }
            last=np;
        }
        void Find(char *S)
        {
            int len=strlen(S);
            int u=0,d=0;
            for(int i=0;i<=id;i++) Max[i]=0;
            for(int i=0;i<len;i++)
            {
                int c=S[i]-'a';
                if(ch[u][c]!=-1) d++,u=ch[u][c];
                else
                {
                    while(u!=-1&&ch[u][c]==-1) u=pre[u];
                    if(u!=-1) d=step[u]+1,u=ch[u][c];
                    else u=0,d=0;
                }
                Max[u]=max(Max[u],d);//更新
            }
            for(int i=id;i>=1;i--) Max[pre[i]]=max(Max[pre[i]],Max[i]);
            for(int i=0;i<=id;i++) Min[i]=min(Min[i],Max[i]);
        }
        int GetAns()
        {
            int ret=0;
            for(int i=0;i<=id;i++) ret=max(ret,Min[i]);
            return ret;
        }
    }sam;
    char S[maxn];
    int main()
    {
        scanf("%s",S);
        int len=strlen(S);
        sam.init();
        for(int i=0;i<len;i++) sam.Insert(S[i]-'a');
        while(scanf("%s",S)!=EOF) sam.Find(S);
        printf("%d
    ",sam.GetAns());
        return 0;
    }
    View Code
  • 相关阅读:
    搭建一个简单的springMVC框架
    java枚举使用
    java中枚举类型的使用
    java递归算法
    JAVA递归算法及经典递归例子 对于这个汉诺塔问题
    java斐波纳契数列
    要求给一个数值,计算它的阶乘
    AcWing2193 分配问题(二分图最优匹配)
    2020上海大学校赛L 动物森友会(网络流+二分)
    BZOJ2654 tree(wqs二分)
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5803045.html
Copyright © 2020-2023  润新知