// mt19937 -> efficient pseudo-random number generator like rand()
// 70 bcz [26+26] for upper + lowercase alphabets + 10 for '0' to '9'
// and base must be greather than max. value of s[i]
mt19937 rng( ( uint32_t ) chrono:: steady_clock :: now ( ) .time_since_epoch ( ) .count ( ) ) ;
const int MOD1 = 1e9 + 7 ;
const int MOD2 = 1e9 + 9 ;
// uniform_int_distribution<int> --> long long int must be used here
const int base1 = uniform_int_distribution< int > ( 70 , MOD1 - 1 ) ( rng) ;
const int base2 = uniform_int_distribution< int > ( 70 , MOD2 - 1 ) ( rng) ;
const int N = 5e5 + 100 ;
int hash1[ N] , hash2[ N] , x1[ N] , x2[ N] , inv1[ N] , inv2[ N] ;
int mod_add( int a, int b, int mod)
{
int tmp = ( a + b) % mod;
if ( tmp < 0 )
tmp + = mod;
return tmp;
}
int mod_mul( int a, int b, int mod)
{
int tmp = ( a * 1LL * b) % mod;
if ( tmp < 0 )
tmp + = mod;
return tmp;
}
int binExpo( int a, int b, int mod)
{
int tmp = 1 ;
while ( b)
{
if ( b % 2 )
tmp = mod_mul( tmp, a, mod) ;
a = mod_mul( a, a, mod) ;
b / = 2 ;
}
return tmp;
}
void preCalc( )
{
x1[ 0 ] = x2[ 0 ] = 1 ;
for ( int i = 1 ; i < N; i++ )
{
x1[ i] = mod_mul( x1[ i - 1 ] , base1, MOD1) ;
x2[ i] = mod_mul( x2[ i - 1 ] , base2, MOD2) ;
}
int x_inv1 = binExpo( base1, MOD1 - 2 , MOD1) ;
int x_inv2 = binExpo( base2, MOD2 - 2 , MOD2) ;
inv1[ 0 ] = inv2[ 0 ] = 1 ;
for ( int i = 1 ; i < N; i++ )
{
inv1[ i] = mod_mul( inv1[ i - 1 ] , x_inv1, MOD1) ;
inv2[ i] = mod_mul( inv2[ i - 1 ] , x_inv2, MOD2) ;
}
}
int val( char c)
{
if ( c >= 'a' && c <= 'z' )
return ( c - 'a' + 1 ) ;
if ( c >= 'A' && c <= 'Z' )
return ( c - 'A' + 27 ) ;
if ( c >= '0' && c <= '9' )
return ( c - '0' + 53 ) ;
}
void build( string & s)
{
hash1[ 0 ] = hash2[ 0 ] = val( s[ 0 ] ) ;
for ( int i = 1 ; i < s.size ( ) ; i++ )
{
hash1[ i] = mod_add( hash1[ i - 1 ] , mod_mul( x1[ i] , val( s[ i] ) , MOD1) , MOD1) ;
hash2[ i] = mod_add( hash2[ i - 1 ] , mod_mul( x2[ i] , val( s[ i] ) , MOD2) , MOD2) ;
}
}
// Hash for s[x....y] => x, y are index
pii getHash( int x, int y)
{
int tmp1 = mod_add( hash1[ y] , ( x == 0 ) ? 0 : - hash1[ x - 1 ] , MOD1) ;
tmp1 = mod_mul( tmp1, inv1[ x] , MOD1) ;
int tmp2 = mod_add( hash2[ y] , ( x == 0 ) ? 0 : - hash2[ x - 1 ] , MOD2) ;
tmp2 = mod_mul( tmp2, inv2[ x] , MOD2) ;
// answer = {Hash1, Hash2}
return { tmp1, tmp2} ;
}
Ly8gbXQxOTkzNyAtPiBlZmZpY2llbnQgcHNldWRvLXJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIGxpa2UgcmFuZCgpCi8vIDcwIGJjeiBbMjYrMjZdIGZvciB1cHBlciArIGxvd2VyY2FzZSBhbHBoYWJldHMgKyAxMCBmb3IgJzAnIHRvICc5JwovLyBhbmQgYmFzZSBtdXN0IGJlIGdyZWF0aGVyIHRoYW4gbWF4LiB2YWx1ZSBvZiBzW2ldCgptdDE5OTM3IHJuZygodWludDMyX3QpY2hyb25vOjpzdGVhZHlfY2xvY2s6Om5vdygpLnRpbWVfc2luY2VfZXBvY2goKS5jb3VudCgpKTsKCmNvbnN0IGludCBNT0QxID0gMWU5ICsgNzsKY29uc3QgaW50IE1PRDIgPSAxZTkgKyA5OwoKLy8gdW5pZm9ybV9pbnRfZGlzdHJpYnV0aW9uPGludD4gLS0+IGxvbmcgbG9uZyBpbnQgbXVzdCBiZSB1c2VkIGhlcmUKY29uc3QgaW50IGJhc2UxID0gdW5pZm9ybV9pbnRfZGlzdHJpYnV0aW9uPGludD4oNzAsIE1PRDEgLSAxKShybmcpOwpjb25zdCBpbnQgYmFzZTIgPSB1bmlmb3JtX2ludF9kaXN0cmlidXRpb248aW50Pig3MCwgTU9EMiAtIDEpKHJuZyk7Cgpjb25zdCBpbnQgTiA9IDVlNSArIDEwMDsKaW50IGhhc2gxW05dLCBoYXNoMltOXSwgeDFbTl0sIHgyW05dLCBpbnYxW05dLCBpbnYyW05dOwoKaW50IG1vZF9hZGQoaW50IGEsIGludCBiLCBpbnQgbW9kKQp7CiAgICBpbnQgdG1wID0gKGEgKyBiKSAlIG1vZDsKICAgIGlmICh0bXAgPCAwKQogICAgICAgIHRtcCArPSBtb2Q7CiAgICByZXR1cm4gdG1wOwp9CgppbnQgbW9kX211bChpbnQgYSwgaW50IGIsIGludCBtb2QpCnsKICAgIGludCB0bXAgPSAoYSAqIDFMTCAqIGIpICUgbW9kOwogICAgaWYgKHRtcCA8IDApCiAgICAgICAgdG1wICs9IG1vZDsKICAgIHJldHVybiB0bXA7Cn0KCmludCBiaW5FeHBvKGludCBhLCBpbnQgYiwgaW50IG1vZCkKewogICAgaW50IHRtcCA9IDE7CiAgICB3aGlsZSAoYikKICAgIHsKICAgICAgICBpZiAoYiAlIDIpCiAgICAgICAgICAgIHRtcCA9IG1vZF9tdWwodG1wLCBhLCBtb2QpOwogICAgICAgIGEgPSBtb2RfbXVsKGEsIGEsIG1vZCk7CiAgICAgICAgYiAvPSAyOwogICAgfQogICAgcmV0dXJuIHRtcDsKfQoKdm9pZCBwcmVDYWxjKCkKewogICAgeDFbMF0gPSB4MlswXSA9IDE7CiAgICBmb3IgKGludCBpID0gMTsgaSA8IE47IGkrKykKICAgIHsKICAgICAgICB4MVtpXSA9IG1vZF9tdWwoeDFbaSAtIDFdLCBiYXNlMSwgTU9EMSk7CiAgICAgICAgeDJbaV0gPSBtb2RfbXVsKHgyW2kgLSAxXSwgYmFzZTIsIE1PRDIpOwogICAgfQoKICAgIGludCB4X2ludjEgPSBiaW5FeHBvKGJhc2UxLCBNT0QxIC0gMiwgTU9EMSk7CiAgICBpbnQgeF9pbnYyID0gYmluRXhwbyhiYXNlMiwgTU9EMiAtIDIsIE1PRDIpOwogICAgaW52MVswXSA9IGludjJbMF0gPSAxOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPCBOOyBpKyspCiAgICB7CiAgICAgICAgaW52MVtpXSA9IG1vZF9tdWwoaW52MVtpIC0gMV0sIHhfaW52MSwgTU9EMSk7CiAgICAgICAgaW52MltpXSA9IG1vZF9tdWwoaW52MltpIC0gMV0sIHhfaW52MiwgTU9EMik7CiAgICB9Cn0KCmludCB2YWwoY2hhciBjKQp7CiAgICBpZiAoYyA+PSAnYScgJiYgYyA8PSAneicpCiAgICAgICAgcmV0dXJuIChjIC0gJ2EnICsgMSk7CgogICAgaWYgKGMgPj0gJ0EnICYmIGMgPD0gJ1onKQogICAgICAgIHJldHVybiAoYyAtICdBJyArIDI3KTsKCiAgICBpZiAoYyA+PSAnMCcgJiYgYyA8PSAnOScpCiAgICAgICAgcmV0dXJuIChjIC0gJzAnICsgNTMpOwp9Cgp2b2lkIGJ1aWxkKHN0cmluZyAmcykKewogICAgaGFzaDFbMF0gPSBoYXNoMlswXSA9IHZhbChzWzBdKTsKICAgIGZvciAoaW50IGkgPSAxOyBpIDwgcy5zaXplKCk7IGkrKykKICAgIHsKICAgICAgICBoYXNoMVtpXSA9IG1vZF9hZGQoaGFzaDFbaSAtIDFdLCBtb2RfbXVsKHgxW2ldLCB2YWwoc1tpXSksIE1PRDEpLCBNT0QxKTsKICAgICAgICBoYXNoMltpXSA9IG1vZF9hZGQoaGFzaDJbaSAtIDFdLCBtb2RfbXVsKHgyW2ldLCB2YWwoc1tpXSksIE1PRDIpLCBNT0QyKTsKICAgIH0KfQoKLy8gSGFzaCBmb3Igc1t4Li4uLnldID0+IHgsIHkgYXJlIGluZGV4CnBpaSBnZXRIYXNoKGludCB4LCBpbnQgeSkKewogICAgaW50IHRtcDEgPSBtb2RfYWRkKGhhc2gxW3ldLCAoeCA9PSAwKSA/IDAgOiAtaGFzaDFbeCAtIDFdLCBNT0QxKTsKICAgIHRtcDEgPSBtb2RfbXVsKHRtcDEsIGludjFbeF0sIE1PRDEpOwoKICAgIGludCB0bXAyID0gbW9kX2FkZChoYXNoMlt5XSwgKHggPT0gMCkgPyAwIDogLWhhc2gyW3ggLSAxXSwgTU9EMik7CiAgICB0bXAyID0gbW9kX211bCh0bXAyLCBpbnYyW3hdLCBNT0QyKTsKICAgIAogICAgLy8gYW5zd2VyID0ge0hhc2gxLCBIYXNoMn0KICAgIHJldHVybiB7dG1wMSwgdG1wMn07Cn0K