haraduka's diary

やる気が欲しい

Indeedなう本戦B C問題 Palindrome Concatenation

ある文字列を作るために回文を組み合わせるのだが、その回文の長さに応じてコストがあり、そのうちで最小コストの組み合わせをもとめる問題。

普通にやるとdpでO(N^3)。
その文字列が回文であるかどうかを判定するテーブルを、文字列のcenterから広げていくやり方をとればO(N^2)でテーブルが作成できるので、最終的にO(N^2)で間に合う…。
バグらせまくって辛かった…。iとかjが何baseのindexなのかメモるなり統一するなりした方がいいですね。

    int N; cin >> N;
    string S; cin >> S;
    int C[N];
    rep(i, N) cin >> C[i];

    bool IS[N][N];
    memset(IS, false, sizeof(IS));
    for(int center=0; center<N; center++){
        int L = center, R = center;
        while(L >= 0 && R < N && S[L] == S[R]){
            IS[L][R] = true;
            L--; R++;
        }
        L = center, R = center+1;
        while(L >= 0 && R < N && S[L] == S[R]){
            IS[L][R] = true;
            L--; R++;
        }
    }

    int dp[N+1];
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    for(int i=1; i<=N; i++){
        for(int j=0; j<i; j++){
            if(IS[j][i-1] && (dp[i] == -1 || dp[i] > dp[j]+C[i-j-1])){
                dp[i] = dp[j] + C[i-j-1];
            }
        }
    }
    cout << dp[N] << endl;