Typical DP Contest I - イウィ

解法

区間DP.

dp[l][r] := [l, r) で最大何文字取り除けるか
と定義する.
まず,dp[l][r] = max(dp[l][i] + dp[i][r]) (i = l, ..., r) という遷移は,明らかだと思う.
あとは,s[l...r) が完全に取り除ける(つまり dp[l][r] == r - l)場合,そこから端に "iwi" をくっつけられるか,を確認する.
例えば "iiwiwi" なら s[1...4) が "iwi" で,端に "i" + "wi" をくっつけられる.
iwi は 3 文字なので,くっつけられるかは普通に全部調べたらいい.

ソースコード

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    int const n = s.size();
    // [l, r)
    vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
    for(int w = 0; w <= n; ++w) {
        for(int l = 0; l + w <= n; ++l) {
            for(int i = l; i <= l + w; ++i) {
                dp[l][l + w] = max(dp[l][l + w], dp[l][i] + dp[i][l + w]);
            }
            if(dp[l][l + w] != w) {
                continue;
            }
            for(int d = 0; d <= 3; ++d) {
                if(l - d < 0 || n < l + w + 3 - d) {
                    continue;
                }
                auto iwi = s.substr(l - d, d) + s.substr(l + w, 3 - d);
                if(iwi == "iwi") {
                    dp[l - d][l + w + 3 - d] = dp[l][l + w] + 3;
                }
            }
        }
    }

    int res = 0;
    for(int i = 0; i <= n; ++i) {
        for(int j = 0; j <= n; ++j) {
            res = max(dp[i][j], res);
        }
    }
    res /= 3;
    cout << res << endl;
}

感想

以下は全く同じ問題なので練習にどうぞ.
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1611&lang=jp