• [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);
    }
    
  • 相关阅读:
    LeetCode: 18. 4Sum
    LeetCode:15. 3Sum
    Leetcode:1. Two Sum
    tensorflow placeholder
    Tensorflow变量
    13.git的简单使用
    13.Django1.11.6文档
    12.python进程协程异步IO
    12.Flask-Restful
    12.Django思维导图
  • 原文地址:https://www.cnblogs.com/mollnn/p/11776388.html
Copyright © 2020-2023  润新知