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;
}