SPOJ 1811. POJ 2774 . 最大公共子串

Description

给出两个字符串 a,b ,求 a 和 b 的最大公共子串,字符串长度为 500000。

Solution

  • 可以用后缀数组做,将两个字符串接起来,中间用特殊的分隔符相连。

  • 求出 Height 数组之后,就可以利用 Height 数组的性质进行计算了!

  • 对于一个 i ,如果 sa[i] sa[i1] 的位置分别属于 a b ,那么 height[i] 就是合法的。

  • 求最大值即可。时间复杂度 O(N log N)

Code

#include<cstdio>
using namespace std;
const int N=5e5+5;
int n,m=27,len,ans;
int sa[N],rank[N],r1[N],height[N],tax[N];
int s[N];
inline void readln()
{
    char ch=getchar();
    while(ch<'a' || ch>'z') ch=getchar();
    while(ch>='a' && ch<='z') s[++n]=ch-'a'+1,ch=getchar();
}
inline void csort()
{
    for(int i=1;i<=m;i++) tax[i]=0;
    for(int i=1;i<=n;i++) tax[rank[i]]++;
    for(int i=1;i<=m;i++) tax[i]+=tax[i-1];
    for(int i=n;i;i--) sa[tax[rank[r1[i]]]--]=r1[i];
}
inline void SA()
{
    for(int i=1;i<=n;i++) rank[r1[i]=i]=s[i];
    csort();
    for(int j=1,p=0;j<=n;j<<=1,m=p,p=0)
    {
        for(int i=n-j+1;i<=n;i++) r1[++p]=i;
        for(int i=1;i<=n;i++)
            if(sa[i]>j) r1[++p]=sa[i]-j;
        csort();
        for(int i=1;i<=n;i++) r1[i]=rank[i];
        rank[sa[1]]=p=1;
        for(int i=2;i<=n;i++)
            rank[sa[i]]=(r1[sa[i]]==r1[sa[i-1]] && r1[sa[i]+j]==r1[sa[i-1]+j])?p:++p;
    }
    for(int i=1,lcp=0;i<=n;height[rank[i++]]=lcp)
    {
        if(lcp) lcp--;
        while(s[i+lcp]==s[sa[rank[i]-1]+lcp]) lcp++;
    }
}
int main()
{
    readln(),s[len=++n]=m,readln(),SA();
    for(int i=2;i<=n;i++)
        if(height[i]>ans && sa[i]<len^sa[i-1]<len) ans=height[i];
    printf("%d",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值