计蒜客 Infinite Fraction Path

icpc2017沈阳

判断两个字符串的字典序大小,通过2017icpc青岛站的suffix那题,我学会了这种方法。不过这题无法直接二分长度,可以通过倍增来进行预处理。

通过这题,我对倍增有了新的认识。ne[x][0]是x走一步,不包含x。

还有很重要一点hash的base不可以取26,10这种东西,一定需要大质数才行。这题取11会wa

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 200005;
const ull base = 131;
ull pw[1000005];
ull ha[maxn][21];
int d[maxn],ne[maxn][21],n;
void init(int n){
    pw[0] = 1;
    for( int i = 1;i <= n;i++ ){
        pw[i] = pw[i-1]*base;
    }
}
int lcp( int& x,int& y ){
    int len = 0;
    for( int i = 19;i >= 0;i-- ){
            if( ha[x][i] == ha[y][i] ){
                x = ne[x][i],y = ne[y][i];
                len += 1<<i;
            }
            if(len > n ) break;
    }
    return len;
}
int main(){
    init(1000000);
    int T,ca = 0;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for( int i = 0;i < n;i++ ){
            scanf("%1d",&d[i]);
        }
        for( int i = 0;i < n;i++ ){
            ne[i][0] = (1LL*i*i+1)%n;
            ha[i][0] = d[ne[i][0]];
        }
        for( int i = 1;i <= 19;i++ ){
            for( int j = 0;j < n;j++ ){
                ne[j][i] = ne[ ne[j][i-1] ][i-1];
                ha[j][i] = ha[ j ][ i-1 ] * pw[ 1<<(i-1) ] + ha[ ne[j][i-1] ][ i-1 ] ;
            }
        }
        //cout << pow( 2,19 ) << endl;
        int pos = 0;
        for( int i = 1;i < n;i++ ){
            if( d[i] > d[pos] ){
                pos = i;
            }else if( d[i] == d[pos] ){
                int x = pos,y = i;
                int len = lcp( x,y );
                int xx = ne[x][0],yy = ne[y][0];
                if( len < n-1 && d[xx] < d[yy] ){
                    pos = i;
                }
            }
        }
        printf("Case #%d: ",++ca);
        for( int i = 1;i <= n;i++ ){
            printf("%d",d[pos]);
            pos = ne[pos][0];
        }
        puts("");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值