洛谷P4324 扭动的回文串 [JSOI2016] manacher+哈希

正解:manacher+哈希

解题报告:

传送门

要不要先解释下题意,,,我开始看了半天来着QAQ

大概就,要求一个最长的回文串

这个回文串有两种构成可能

一种是单从一个串中拿出来的连续一段

另一种是两个串各拿出连续一段拼起来,其中这两段需要满足第一段的右端点坐标=第二段的左端点坐标

欧克然后看题趴QwQ

首先但从一个串中拿就直接跑个manacher就好

然后问题就在这个从两个串中各拿出一段

首先如果这是个回文串,显然它一定是有一段的一侧是本来就有的回文串,然后另一侧和另一个串构成回文串这样子的QwQ

(umm可能那个本来就有的回文串是空的我不管特殊情况但也差不多来着QwQ

然后仔细思考一下可以发现显然这段本来就有的回文串一定是越长越好的,懒得证了显然不会更劣的QwQ

所以就可以直接枚举每个回文串,然后求一下它的两侧能拓展多少就好

然后这个求,首先显然是有可二分性的,所以就二分+哈希判断下就好

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define ll unsigned long long
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)

const int N=3e5+10,bas=2333;
int n,str_cnt,f[2][N],as;
ll poww[N],hsh[N][2];
char a[N],b[N],c[N];

il int read()
{
    rc ch=gc;ri x=0;rb y=1;
    while(ch!='-' && (ch<'0' || ch>'9'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il void manacher(rc *s,ri *g)
{
    s[0]='$';ri id=0,mx=0;
    rp(i,1,n){g[i]=mx>i?min(g[2*id-i],mx-i):0;while(s[i-g[i]-1]==s[i+g[i]+1])++g[i];if(g[i]+i>mx)mx=g[i]+i,id=i;}
}
il ll check(ri gdgs,ri l,ri r)
{
    if(gdgs)return hsh[l][1]-1ll*hsh[r+1][1]*poww[r-l+1];
    return hsh[r][0]-1ll*hsh[l-1][0]*poww[r-l+1];
}
il int cal(ri l,ri r)
{
    ri as_l=0,as_r=min(l,n-r+1);
    while(as_l<as_r)
    {
        ri mid=(as_l+as_r)>>1;
        if(check(0,l-(mid+1)+1,l)==check(1,r,r+(mid+1)-1))as_l=mid+1;else as_r=mid;
    }
    return as_l;
}

int main()
{
    freopen("4324.in","r",stdin);freopen("4324.out","w",stdout);
    n=read();scanf("%s%s",a+1,b+1);
    poww[0]=1;
    rp(i,1,n)poww[i]=poww[i-1]*bas;
    rp(i,1,n)hsh[i][0]=hsh[i-1][0]*bas+a[i];
    my(i,n,1)hsh[i][1]=hsh[i+1][1]*bas+b[i];
    rp(i,1,n)c[i]=a[i];str_cnt=0;rp(i,1,n)a[++str_cnt]='*',a[++str_cnt]=c[i];a[++str_cnt]='*';
    rp(i,1,n)c[i]=b[i];str_cnt=0;rp(i,1,n)b[++str_cnt]='*',b[++str_cnt]=c[i];b[++str_cnt]='*';
    n=(n<<1)|1;manacher(a,f[0]);manacher(b,f[1]);
    rp(i,1,n){ri l=(i-f[0][i]+1)/2,r=(i+f[0][i])/2;as=max(as,f[0][i]+(cal(l-1,r)<<1));}
    rp(i,1,n){ri l=(i-f[1][i]+1)/2,r=(i+f[1][i])/2;as=max(as,f[1][i]+(cal(l,r+1)<<1));}
    printf("%d\n",as);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10655668.html