[GDOI2014]beyond 扩展KMP+并查集

题目等价于求给定两个长度都为 n n 的串A,B,求一个最大的 L L 使得A1..L B1..L B 1.. L 循环同构。
我们先对 A,B A , B 互相做一遍扩展KMP,记 Ai..n A i . . n B B 的LCP为exai exb e x b 同理。
循环同构一定是存在 x x ,使得A1..x=BLx+1..L , Ax+1..L=B1..Lx,我们枚举 x x ,那么就是要在找到最大的p[1..exax+1+1]满足 exbpx e x b p ≥ x 中,也就找到了一个 L=x+p L = x + p
我们用一个类似并查集的方法来维护这个,设 fai f a i i i 左边第一个合法的p,考虑到 x x 是递增的,如果某个exbj<x就把 j j <script type="math/tex" id="MathJax-Element-2216">j</script>缩掉即可。
代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2000010
using namespace std;
int n,nxta[N],nxtb[N],exa[N],exb[N],fa[N];
char a[N],b[N];
void ex_kmp(char s[],char t[],int nxt[],int ex[])
{
    int st=1,ed=0;
    nxt[1]=n;
    for(int i=2;i<=n;i++)
    {
        if(nxt[i-st+1]<ed-i+1) {nxt[i]=nxt[i-st+1];continue;}
        ed=max(i-1,ed);
        for(int j=ed-i+1;ed<n&&t[ed+1]==t[j+1];ed++,j++);
        st=i;nxt[i]=ed-i+1;
    }
    st=1;ed=0;
    for(int i=1;i<=n;i++)
    {
        if(nxt[i-st+1]<ed-i+1) {ex[i]=nxt[i-st+1];continue;}
        ed=max(i-1,ed);
        for(int j=ed-i+1;ed<n&&s[ed+1]==t[j+1];ed++,j++);
        st=i;ex[i]=ed-i+1;
    }
}
int getfa(int v,int x)
{
    if(!v||exb[v]>=x) return v;
    return (fa[v]=getfa(fa[v],x));
}
int main()
{
    scanf("%d%s%s",&n,a+1,b+1);
    ex_kmp(a,b,nxtb,exa);
    ex_kmp(b,a,nxta,exb);
    for(int i=1;i<=n;i++)
        fa[i]=i-1;  
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int tmp=getfa(exa[i+1]+1,i);
        //cout<<i<<' '<<tmp<<endl;
        if(tmp) ans=max(ans,tmp+i-1);
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值