0w1

CFR 159 D. Palindrome pairs ( DP )

Problem - D - Codeforces
題意:
給一個字串s,求有多少整數組 ( a, b, x, y ) 滿足 s[ a .. b ] 為回文且 s[ x .. y ] 為回文。
解法:
先O( | S | ^ 2 )預處理使得可以用常數時間判斷一個子字串是否為回文。再額外預處理前綴和 spal[ t ] 存儲前 t 個字母的子字串中的回文數。裡接著考慮動態規劃
dp[ i ] : 考慮完 i 個字元時的答案
dp[ i ] = dp[ i - 1 ] + SIGMA{ spal[ j ] | 所有 j 滿足 s[ j .. i ] 為回文 }

string seq;

void init(){
    cin >> seq;
}

vvi is_pal; // [ l, r ]
vi spal;
vl dp;

void preprocess(){
    is_pal = vvi( seq.size() + 1, vi( seq.size() + 1 ) );
    for( int i = 0; i < seq.size(); ++i )
        is_pal[ i ][ i ] = 1;
    for( int i = 0; i + 2 <= seq.size(); ++i )
        if( seq[ i ] == seq[ i + 1 ] )
            is_pal[ i ][ i + 1 ] = 1;
    for( int len = 1; len + 2 <= seq.size(); ++len )
        for( int i = 1; i + len < seq.size(); ++i )
            if( is_pal[ i ][ i + len - 1 ] )
                if( seq[ i - 1 ] == seq[ i + len ] )
                    is_pal[ i - 1 ][ i + len ] = 1;
    spal = vi( seq.size() + 1 );
    for( int i = 0; i < seq.size(); ++i )
        for( int j = i; j < seq.size(); ++j )
            spal[ j + 1 ] += is_pal[ i ][ j ];
    for( int i = 0; i < seq.size(); ++i )
        spal[ i + 1 ] += spal[ i ];
    dp = vl( seq.size() + 1 );
    for( int i = 0; i < seq.size(); ++i ){
        dp[ i + 1 ] += dp[ i ];
        for( int j = 0; j <= i; ++j )
            if( is_pal[ j ][ i ] )
                dp[ i + 1 ] += spal[ j ];
    }
}

void solve(){
    cout << dp[ ( int ) seq.size() ] << endl;
}