0w1

BWT and IBWT

Burrows-Wheeler Transform and its inverse.
See this and this.

// BWT, O( N ^ 2 lg N ) due to SA
string s;
int slen;
vi sa;

bool sa_cmp( const int i, const int j ){
    return s.substr( i, slen ) < s.substr( j, slen );
}

void solve(){
    cin >> s;
    slen = s.size();
    sa = vi( slen );
    s += s;
    for( int i = 0; i < slen; ++i )
        sa[ i ] = i;
    stable_sort( sa.begin(), sa.end(), sa_cmp );
    for( int i = 0; i < slen; ++i )
        cout << s[ ( sa[ i ] + slen - 1 ) % slen ];
}
// IBWT, O( N )
string s;
int slen;
vi nxt;

void solve(){
    cin >> s;
    slen = s.size();
    nxt = vi( slen );
    vvi idx( 256 );
    for( int i = 0; i < slen; ++i )
        idx[ s[ i ] ].push_back( i );
    for( int i = 0, c = 0; i < 256; ++i )
        for( int j = 0; j < idx[ i ].size(); ++j )
            nxt[ c++ ] = idx[ i ][ j ];
    vector< char > ans;
    for( int i = 0, p = 0; i < slen; ++i )
        ans.push_back( s[ p = nxt[ p ] ] );
    for( int i = 1; i < ans.size(); ++i )
        cout << ans[ i ];
    cout << ans[ 0 ];
}