poj2774 Long Long Message

【题意】

两个串的最长公共连续子串

【分析】

直接连到一起,中间加上间隔符,求height之后,二分答案判断在是否属于两个串

【代码】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2e5+5;
int n;
char a[maxn],s[maxn],b[maxn];
int h[maxn],maxi,id[maxn];
int sa[maxn],rk[maxn],oldrk[maxn],cnt[maxn],fz[maxn];
bool cmp(int x,int y,int w)
{
    return oldrk[x]==oldrk[y] && oldrk[x+w]==oldrk[y+w];
}
void calcsa()
{
    int m=233;
    for(int i=0;i<=m;i++) cnt[i]=0;
    for(int i=1;i<=n;i++) cnt[rk[i]=a[i]]++;
    for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
    int i,p;
    for(int w=1;;w<<=1,m=p)
    {
        for(p=0,i=n;i>n-w;i--) id[++p]=i;
        for(i=1;i<=n;i++) if(sa[i]>w) id[++p]=sa[i]-w;
        for(i=0;i<=m;i++) cnt[i]=0;
        for(i=1;i<=n;i++) cnt[fz[i]=rk[id[i]]]++;
        for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
        for(i=n;i>=1;i--) sa[cnt[fz[i]]--]=id[i];
        for(i=1;i<=n;i++) oldrk[i]=rk[i];
        for(p=0,i=1;i<=n;i++) rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
        if(p==n)
        {
            for(i=1;i<=n;i++) sa[rk[i]]=i;
            break;
        }
    }
}
void calch()
{
    int i,k=0;
    for(i=1;i<=n;i++)
    {
        if(k) k--;
        while(a[i+k]==a[sa[rk[i]-1]+k]) k++;
        h[rk[i]]=k;
    }
}
int len1;
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%s",s+1);
    scanf("%s",b+1);
    len1=strlen(s+1);
    for(int i=1;i<=len1;i++) a[i]=s[i];
    n+=len1;
    s[++n]=1;
    int len2=strlen(b+1);
    for(int i=1;i<=len2;i++) a[i+n]=b[i];
    n+=len2;
    calcsa(); calch();
    int ans=0;
    for(int i=2;i<n;i++)
    {
        if(0<=sa[i] && sa[i]<=len1 && len1+1<sa[i-1]) ans=max(ans,h[i]);
        if(0<=sa[i-1] && sa[i-1]<=len1 && len1+1<sa[i]) ans=max(ans,h[i]);
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2021-04-27 19:46  andyc_03  阅读(30)  评论(0编辑  收藏  举报