zoukankan      html  css  js  c++  java
  • BZOJ4755 JSOI2016扭动的回文串(二分答案+哈希)

      显然答案应该是由单串以某位置为中心的极长回文串继续在另一个串里拓展得到的。枚举中间位置二分答案,哈希判断即可。注意考虑清楚怎么处理偶回文,比如像manacher一样加分隔符。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    #define ul unsigned long long
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,ans;
    ul ha[N],rha[N],hb[N],rhb[N],p[N];
    char a[N],b[N],s1[N],s2[N];
    ul hash(ul *a,int l,int r,int op)
    {
        return a[r]-a[l-op]*p[abs(r-l)+1];
    }
    void solve(ul *a,ul *ra,ul *b,ul *rb,int op,int n)
    {
        for (int i=1;i<=n;i++)
        {
            int l=0,r=min(n-i,i-1),len=0;
            while (l<=r)
            {
                int mid=l+r>>1;
                if (hash(a,i-mid,i,1)==hash(ra,i+mid,i,-1)) len=mid,l=mid+1;
                else r=mid-1;
            }
            ans=max(ans,len);
            l=1,r=min(i-len+1,n-i-len);
            while (l<=r)
            {
                int mid=l+r>>1;
                if (op?hash(b,i-len-mid+1,i-len,1)==hash(ra,i+len+mid,i+len+1,-1):hash(a,i-len-mid,i-len-1,1)==hash(rb,i+len+mid-1,i+len,-1)) ans=max(ans,len+mid),l=mid+1;
                else r=mid-1;
            }
        }
    }
    void work(int n)
    {
        n=n*2+2;
        for (int i=1;i<=n;i++) ha[i]=ha[i-1]*509+a[i];
        for (int i=n;i>=1;i--) rha[i]=rha[i+1]*509+a[i];
        for (int i=1;i<=n;i++) hb[i]=hb[i-1]*509+b[i];
        for (int i=n;i>=1;i--) rhb[i]=rhb[i+1]*509+b[i];
        p[0]=1;for (int i=1;i<=n;i++) p[i]=p[i-1]*509;
        solve(ha,rha,hb,rhb,0,n),solve(hb,rhb,ha,rha,1,n);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4755.in","r",stdin);
        freopen("bzoj4755.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        scanf("%s",s1+1),scanf("%s",s2+1);
        for (int i=n;i>=1;i--) a[i*2+2]='$',a[i*2+1]=s1[i];a[2]='$';a[1]='#';
        for (int i=n;i>=1;i--) b[i*2+1]='$',b[i*2]=s2[i];b[1]='$';b[n*2+2]='@';
        work(n);
        for (int i=n;i>=1;i--) a[i*2+1]='$',a[i*2]=s1[i];a[1]='$';a[n*2+2]='@';
        for (int i=n;i>=1;i--) b[i*2+2]='$',b[i*2+1]=s2[i];b[2]='$';b[1]='#';
        work(n);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Nero8刻录引导系统光盘镜像图文教程
    C#多线程与并行编程方面的电子书,中英文版本
    [转]C#通过委托更新UI(异步加载)
    [PHP] 6种负载均衡算法
    [GIt] 团队工作效率分析工具gitstats
    [Git] git代码统计
    [Git] 写文章 史上最全文献检索、阅读及管理攻略
    [Git] 谷歌的代码管理
    [JQuery] jQuery选择器ID、CLASS、标签获取对象值、属性、设置css样式
    [Mongo] 解决mongoose不支持条件操作符 $gt$gte:$lte$ne $in $all $not
  • 原文地址:https://www.cnblogs.com/Gloid/p/9955835.html
Copyright © 2011-2022 走看看