zoukankan      html  css  js  c++  java
  • SPOJ LCS2

    LCS2 - Longest Common Substring II

    no tags 

    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
    

    Notice: new testcases added

    题意:

      求多个串的最长公共字串

    题解:

      将第一个串建立后缀自动机

      根据拓扑排序更新每个状态节点下所能向前延伸的长度,每次匹配一个串都更新即可

      是不是很模糊

    #include <bits/stdc++.h>
    inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
    using namespace std;
    
    const int N = 3e5+7;
    
    const long long mod = 1000000007;
    
    int isPlus[N * 2],endpos[N * 2];int d[N * 2];
    int tot,slink[2*N],trans[2*N][28],minlen[2*N],maxlen[2*N],pre;
    int newstate(int _maxlen,int _minlen,int* _trans,int _slink){
        maxlen[++tot]=_maxlen;minlen[tot]=_minlen;
        slink[tot]=_slink;
        if(_trans)for(int i=0;i<26;i++)trans[tot][i]=_trans[i],d[_trans[i]]+=1;
        return tot;
    }
    int add_char(char ch,int u){
        int c=ch-'a',v=u;
        int z=newstate(maxlen[u]+1,-1,NULL,0);
        isPlus[z] = 1;
        while(v&&!trans[v][c]){trans[v][c]=z;d[z]+=1;v=slink[v];}
        if(!v){ minlen[z]=1;slink[z]=1;return z;}
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]){slink[z]=x;minlen[z]=maxlen[x]+1;return z;}
        int y=newstate(maxlen[v]+1,-1,trans[x],slink[x]);
        slink[z]=slink[x]=y;minlen[x]=minlen[z]=maxlen[y]+1;
        while(v&&trans[v][c]==x){trans[v][c]=y;d[x]--,d[y]++;v=slink[v];}
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void init_sam() {
        for(int i = 1; i <= tot; ++i)
            for(int j = 0; j < 26; ++j) trans[i][j] = 0;
        pre = tot = 1;
    }
    
    int dp[N],ans,n,vis[N],cnt[N],pos[N];
    char a[N];
    int main() {
        int f = 1;
        while(scanf("%s",a)!=EOF) {
            n = strlen(a);
            if(f) {
                init_sam();
                for(int i = 0; i < n; ++i)
                    pre = add_char(a[i],pre);
                f = 0;
                for(int i = 0; i <= n; ++i)cnt[i] = 0;
                for(int i = 2; i <= tot; ++i)cnt[maxlen[i]] += 1;
                for(int i = 1; i <= n; ++i)cnt[i]+=cnt[i-1];
                for(int i = tot; i >= 2; --i)pos[cnt[maxlen[i]]--] = i;
            }
            else
            {
                int now = 1,sum = 0;
                for(int i = 0; i < n; ++i)
                {
                    if(trans[now][a[i]-'a']) {
                        sum++;
                        now = trans[now][a[i]-'a'];
                        dp[now] = max(dp[now],sum);
                    }
                    else {
                        while(now) {
                            now = slink[now];
                            if(trans[now][a[i]-'a']) break;
                        }
                        if(!now) now = 1,sum = 0;
                        else
                        {
                            sum = maxlen[now] + 1;
                            now = trans[now][a[i]-'a'];
                            dp[now] = max(dp[now],sum);
                        }
                    }
                }
                for(int i = tot; i >= 2; --i) {
                    int v = pos[i];
                    maxlen[v] = min(maxlen[v],dp[v]);
                    dp[slink[v]] = max(dp[slink[v]],dp[v]);
                    dp[v] = 0;
                }
            }
        }
        int ans = 0;
        for(int i = 2; i <= tot; ++i) {
            ans = max(ans,maxlen[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    /*
    aabbcd
    babbefg
    cdbbabb
    */
  • 相关阅读:
    【cdq分治】【P4390】[BOI2007]Mokia 摩基亚
    【树上莫队】【SP10707】 COT2
    【费用流】【网络流24题】【P1251】 餐巾计划问题
    【费用流】【网络流24题】【P4014】 分配问题
    【MST】P2323 [HNOI2006]公路修建问题
    【组合数学】【P5216】DLS采花
    【线段树】【P4198】 楼房重建
    【整体二分】【P3527】 [POI2011]MET-Meteors
    【线性基/神仙题】P4151 [WC2011]最大XOR和路径
    【枚举&数据结构】【P2484】 [SDOI2011]打地鼠
  • 原文地址:https://www.cnblogs.com/zxhl/p/7617060.html
Copyright © 2011-2022 走看看