• [Codechef SSTORY] A Story with Strings


    [Codechef SSTORY] A Story with Strings

    Description

    给定两个字符串,求它们的最长公共子串。如果解不唯一,输出最先在第二个字符串中出现的那个。

    Solution

    仍然考虑二分答案,然后每次检验连续的一块中是否有来自两个串的后缀出现。

    最后额外处理一次,每次检验连续的一块中是否有来自两个串的后缀出现,在有的情况下利用所有来源于第二个串的后缀得到可能的最小位置即可。

    竟然二分边界忘记加一,我TM真是个憨憨

    #include <bits/stdc++.h>
    using namespace std;
    
    int n,l1,l2,m=256,sa[1000005],y[1000005],u[1000005],v[1000005],o[1000005],r[1000005],h[1000005],T;
    char str[1000005];
    long long ans;
    
    int main()
    {
        scanf("%s",str+1);
        l1=strlen(str+1);
        str[l1+1]='$';
        scanf("%s",str+l1+2);
        l2=strlen(str+l1+2);
        n=l1+l2+1;
    
        for(int i=1; i<=n; i++) u[str[i]]++;
        for(int i=1; i<=m; i++) u[i]+=u[i-1];
        for(int i=n; i>=1; i--) sa[u[str[i]]--]=i;
        r[sa[1]]=1;
        for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
    
        for(int l=1; r[sa[n]]<n; l<<=1)
        {
            memset(u,0,sizeof u);
            memset(v,0,sizeof v);
            memcpy(o,r,sizeof r);
            for(int i=1; i<=n; i++) u[r[i]]++, v[r[i+l]]++;
            for(int i=1; i<=n; i++) u[i]+=u[i-1], v[i]+=v[i-1];
            for(int i=n; i>=1; i--) y[v[r[i+l]]--]=i;
            for(int i=n; i>=1; i--) sa[u[r[y[i]]]--]=y[i];
            r[sa[1]]=1;
            for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
        }
        {
            int i,j,k=0;
            for(int i=1; i<=n; h[r[i++]]=k)
                for(k?k--:0,j=sa[r[i]-1]; str[i+k]==str[j+k]; k++);
        }
    
        int L=1,R=min(l1,l2)+1;
        while(L<R)
        {
            int mid=(L+R)/2, flag=0;
            int i=1,j=1;
            while(i<=n && j<=n)
            {
                j=i;
                while(h[j+1]>=mid) ++j;
                int fg1=0,fg2=0;
                for(int k=i; k<=j; k++)
                {
                    if(sa[k]<=l1) fg1=1;
                    if(sa[k]>l1+1) fg2=1;
                }
                if(fg1 && fg2) flag=1;
                i=j+1;
            }
            if(flag) L=mid+1;
            else R=mid;
        }
    
        if(L-1==0)
        {
            printf("0
    ");
            return 0;
        }
        int mx = n+1;
        int i=1,j=1;
        while(i<=n && j<=n)
        {
            j=i;
            while(h[j+1]>=L-1) ++j;
            int fg1=0,fg2=0;
            for(int k=i; k<=j; k++)
            {
                if(sa[k]<=l1) fg1=1;
                if(sa[k]>l1+1) fg2=1;
            }
            if(fg1 && fg2)
            {
                for(int k=i; k<=j; k++)
                    if(sa[k]>l1+1) mx=min(mx,sa[k]);
            }
            i=j+1;
        }
        for(int k=0; k<L-1; k++) printf("%c",str[mx+k]);
        printf("
    %d
    ",L-1);
    }
    
  • 相关阅读:
    nginx内置高可用配置与第三方高可用模块nginx_ustream_check_mudule配置
    nginx+php,nginx+tomcat动静分离实战
    面向对象三大特性之多态与多态性
    面向对象三大特性之组合
    面向对象三大特性之继承与派生
    面向对象编程初探
    常用模块
    模块
    函数
    文件处理
  • 原文地址:https://www.cnblogs.com/mollnn/p/11776388.html
Copyright © 2020-2023  润新知