zoukankan      html  css  js  c++  java
  • [bzoj4755][Jsoi2016]扭动的回文串

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    JYY有两个长度均为N的字符串A和B。
    一个“扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串与B中的第j个字符到第k个字符组成的子串拼接而成。
    比如,若A=’XYZ’,B=’UVW’,则扭动字符串S(1,2,3)=’XYVW’。
    JYY定义一个“扭动的回文串”为如下情况中的一个:
    1.A中的一个回文串;
    2.B中的一个回文串;
    3.或者某一个回文的扭动字符串S(i,j,k)
    现在JYY希望找出最长的扭动回文串。
    n<=10^5
     
    不难证明最长的扭动回文串是由一个中心的最长的回文串向两边延伸得到的。
    所以先马拉车,然后二分+哈希判断即可。
    还要判断一下两个串分别对称的情况。
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #define MN 200000
    #define rint register int
    #define getchar() (*S++)
    char BB[1<<26],*S=BB;
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9')  ch = getchar();
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x;
    }
    inline char Getchar()
    {
        char c;
        do c=getchar(); while(c<'A'||c>'Z');
        return c;    
    }
    
    int n,mx,pos,Lt[MN+5],Rt[MN+5],ans=0;
    unsigned int f[MN+5],F[MN+5],pw[MN+5];
    char A[MN+5],B[MN+5];
    
    int Solve(int Lt,int Rt)
    {
        int l=1,r=min(Lt,n-Rt+1),mid,ans=0;
        while(l<=r)
        {
            mid=l+r>>1;
            unsigned int ha1,ha2;
            ha1=f[Lt-mid+1]-pw[mid]*f[Lt+1];
            ha2=F[Rt+mid-1]-pw[mid]*F[Rt-1];
            if(ha1==ha2)  ans=mid,l=mid+1;
            else r=mid-1;    
        }
        return ans;
    }
    
    int main()
    {
        fread(BB,1,1<<26,stdin); 
        n=read();pw[0]=1;
        for(rint i=1;i<=n;++i) A[i<<1]=Getchar(),pw[i]=pw[i-1]*39;
        for(rint i=1;i<=n;++i) B[i<<1]=Getchar();
        for(rint i=1;i<=n+1;++i) A[i*2-1]=B[i*2-1]=']'; 
        mx=0,pos=0;n=n*2+1;
        for(rint i=n;i;--i) f[i]=f[i+1]*39+A[i]-'A'+1;
        for(rint i=1;i<=n;++i) F[i]=F[i-1]*39+B[i]-'A'+1;
        for(rint i=1;i<=n;++i)
        {
            if(i<=mx) Lt[i]=min(mx-i+1,Lt[2*pos-i]);
            else Lt[i]=1;
            while(i-Lt[i]>=1&&i+Lt[i]<=n&&A[i-Lt[i]]==A[i+Lt[i]]) ++Lt[i];
            if(Lt[i]+i-1>mx) mx=Lt[i]+i-1,pos=i;
            if(i&1) {if(Lt[i]>1)ans=max(ans,Solve(i-Lt[i],i+Lt[i]-2)+Lt[i]/2*2);}
            else  ans=max(ans,Solve(i-Lt[i],i+Lt[i]-2)+(Lt[i]-1)/2*2+1);    
            ans=max(ans,(Lt[i]-(i%2==0))/2*2+(i%2==0));
        }
        mx=n+1;pos=n+1;
        for(rint i=n;i;--i)
        {
            if(i>=mx) Rt[i]=min(i-mx+1,Rt[2*pos-i]);
            else Rt[i]=1;
            while(i-Rt[i]>=1&&i+Rt[i]<=n&&B[i-Rt[i]]==B[i+Rt[i]]) ++Rt[i];
            if(i-Rt[i]+1<mx) mx=i-Rt[i]+1,pos=i;
            if(i&1){ if(Rt[i]>1) ans=max(ans,Solve(i-Rt[i]+2,i+Rt[i])+Rt[i]/2*2);}
            else ans=max(ans,Solve(i-Rt[i]+2,i+Rt[i])+(Rt[i]-1)/2*2+1); 
            ans=max(ans,(Rt[i]-(i%2==0))/2*2+(i%2==0));
        }
        for(rint x=1;x<=n;++x) 
            if((!(x&1))&&A[x]==B[x]) ans=max(ans,Solve(x-2,x+2)+2);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    改变Prompt默认路径,Change Default Visual Studio Command Prompt Location
    msbuild,Build failed with Error MSB3073 exited with code 1
    the filename directory name or volume label syntax is incorrect
    常用sql语句记录
    EF中多表公共字段,以及设置EntityBase使所有实体类继承自定义类
    一种在MVC3框架里面设置模板页的方法,不使用_ViewStart
    Java内存模型
    Effective Java(1)-创建和销毁对象
    WireShark 查看UDP码流的丢包率
    拖延心理学读后感
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4755.html
Copyright © 2011-2022 走看看