vector< int > suffix_array( string s)
{
int n = s.size ( ) , N = n + 256 ;
vector< int > sa( n) , ra( n) ;
for ( int i = 0 ; i < n; i++ ) sa[ i] = i, ra[ i] = s[ i] ;
for ( int k = 0 ; k < n; k ? k * = 2 : k++ )
{
vector< int > nsa( sa) , nra( n) , cnt( N) ;
for ( int i = 0 ; i < n; i++ ) nsa[ i] = ( nsa[ i] - k + n) % n;
for ( int i = 0 ; i < n; i++ ) cnt[ ra[ i] ] ++ ;
for ( int i = 1 ; i < N; i++ ) cnt[ i] + = cnt[ i - 1 ] ;
for ( int i = n - 1 ; i >= 0 ; i-- ) sa[ -- cnt[ ra[ nsa[ i] ] ] ] = nsa[ i] ;
int r = 0 ;
for ( int i = 1 ; i < n; i++ )
{
if ( ra[ sa[ i] ] ! = ra[ sa[ i - 1 ] ] ) r++ ;
else if ( ra[ ( sa[ i] + k) % n] ! = ra[ ( sa[ i - 1 ] + k) % n] ) r++ ;
nra[ sa[ i] ] = r;
}
ra = nra;
}
return sa;
}
vector< int > kasai( string s, vector< int > sa)
{
int n = s.size ( ) , k = 0 ;
vector< int > ra( n) , lcp( n) ;
for ( int i = 0 ; i < n; i++ ) ra[ sa[ i] ] = i;
for ( int i = 0 ; i < n; i++ )
{
if ( k) k-- ;
if ( ra[ i] == n - 1 ) { k = 0 ; continue ; }
int j = sa[ ra[ i] + 1 ] ;
while ( k < n && s[ ( i + k) % n] == s[ ( j + k) % n] ) k++ ;
lcp[ ra[ i] ] = k;
if ( ra[ ( sa[ ra[ i] ] + 1 ) % n] > ra[ ( sa[ ra[ j] ] + 1 ) % n] ) k = 0 ;
}
return lcp;
}
CnZlY3RvcjxpbnQ+IHN1ZmZpeF9hcnJheShzdHJpbmcgcykKewogICAgaW50IG4gPSBzLnNpemUoKSwgTiA9IG4gKyAyNTY7CiAgICB2ZWN0b3I8aW50PiBzYShuKSwgcmEobik7CiAgICBmb3IoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSBzYVtpXSA9IGksIHJhW2ldID0gc1tpXTsKICAgIGZvcihpbnQgayA9IDA7IGsgPCBuOyBrID8gayAqPSAyIDogaysrKQogICAgewogICAgICAgIHZlY3RvcjxpbnQ+IG5zYShzYSksIG5yYShuKSwgY250KE4pOwogICAgICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspIG5zYVtpXSA9IChuc2FbaV0gLSBrICsgbikgJSBuOwogICAgICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspIGNudFtyYVtpXV0rKzsKICAgICAgICBmb3IoaW50IGkgPSAxOyBpIDwgTjsgaSsrKSBjbnRbaV0gKz0gY250W2kgLSAxXTsKICAgICAgICBmb3IoaW50IGkgPSBuIC0gMTsgaSA+PSAwOyBpLS0pIHNhWy0tY250W3JhW25zYVtpXV1dXSA9IG5zYVtpXTsKCiAgICAgICAgaW50IHIgPSAwOwogICAgICAgIGZvcihpbnQgaSA9IDE7IGkgPCBuOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBpZihyYVtzYVtpXV0gIT0gcmFbc2FbaSAtIDFdXSkgcisrOwogICAgICAgICAgICBlbHNlIGlmKHJhWyhzYVtpXSArIGspICUgbl0gIT0gcmFbKHNhW2kgLSAxXSArIGspICUgbl0pIHIrKzsKICAgICAgICAgICAgbnJhW3NhW2ldXSA9IHI7CiAgICAgICAgfQogICAgICAgIHJhID0gbnJhOwogICAgfQogICAgcmV0dXJuIHNhOwp9Cgp2ZWN0b3I8aW50PiBrYXNhaShzdHJpbmcgcywgdmVjdG9yPGludD4gc2EpCnsKICAgIGludCBuID0gcy5zaXplKCksIGsgPSAwOwogICAgdmVjdG9yPGludD4gcmEobiksIGxjcChuKTsKICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHJhW3NhW2ldXSA9IGk7CiAgICBmb3IoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgewogICAgICAgIGlmKGspIGstLTsKICAgICAgICBpZihyYVtpXSA9PSBuIC0gMSkge2sgPSAwOyBjb250aW51ZTt9CiAgICAgICAgaW50IGogPSBzYVtyYVtpXSArIDFdOwogICAgICAgIHdoaWxlKGsgPCBuICYmIHNbKGkgKyBrKSAlIG5dID09IHNbKGogKyBrKSAlIG5dKSBrKys7CiAgICAgICAgbGNwW3JhW2ldXSA9IGs7CiAgICAgICAgaWYocmFbKHNhW3JhW2ldXSArIDEpICUgbl0gPiByYVsoc2FbcmFbal1dICsgMSkgJSBuXSkgayA9IDA7CiAgICB9CiAgICByZXR1cm4gbGNwOwp9