zoukankan      html  css  js  c++  java
  • 【BZOJ】1692: [Usaco2007 Dec]队列变换

    【算法】字符串hash

    【题解】

    显然如果字母互不相同,贪心取是正确的。

    如果存在字母相同,那么就换成比较后缀和前缀嘛。

    但是要注意,不是后缀和前缀相同就能直接跳跃,每次必须只推一位。

    取模的哈希比自然溢出慢了好多。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=30010,MOD=123456789,base=291;
    ll sum1[maxn],sum2[maxn],p[maxn];
    int n;
    char c,s[maxn];
    int calc1(int L,int R){return (sum1[R]+MOD-sum1[L-1]*p[R-L+1]%MOD)%MOD;}
    int calc2(int L,int R){return (sum2[L]+MOD-sum2[R+1]*p[R-L+1]%MOD)%MOD;}
    bool big(int L,int R){
        if(s[L]!=s[R])return s[L]>=s[R];
        int l=1,r=R-L+2;
         while(l<r){
             int mid=(l+r)>>1;
             if(calc1(L,L+mid-1)==calc2(R-mid+1,R))l=mid+1;
             else r=mid;
         }
         return s[L+l-1]>=s[R-l+1];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            c=getchar();
            while(c<'A'||c>'Z')c=getchar();
            s[i]=c;
        }
        p[0]=1;
        for(int i=1;i<=n;i++)p[i]=p[i-1]*base%MOD;
        for(int i=1;i<=n;i++)sum1[i]=(sum1[i-1]*base+s[i]-'A')%MOD;
        for(int i=n;i>=1;i--)sum2[i]=(sum2[i+1]*base+s[i]-'A')%MOD;
        int L=1,R=n;
        for(int i=1,j=1;i<=n;i++,j++){
            if(!big(L,R)){
                putchar(s[L++]);
            }
            else{
                putchar(s[R--]);
            }
            if(j==80)putchar('
    '),j=0;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ping与telnet的区别
    TCP连接的建立与关闭
    网络的7层协议
    oracle数据库中,分天查询数目
    求某个字符在字符串中的第5个位置
    高精度乘
    高精度加法
    二叉排序树(建树,先序,中序,后序遍历)
    求哈夫曼树的带权路径长度和
    HDU_1237_简单计算器
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7445338.html
Copyright © 2011-2022 走看看