mayoko’s diary

プロコンとかいろいろ。

SRM 686 div1 easy: BracketSequenceDiv1(その 2)

さっきの問題の dp 解です。
mayokoex.hatenablog.com

dp[l][r] = [l, r) の区間における, valid な括弧列の数, とします。

valid な括弧列の生成の仕方は,

  • l 番目を無視する(区間 [l+1, r) )
  • l 番目と i 番目が一致する時, [l+1, i) と [i+1, r) に分けて考える

の 2 通りがあるので, 両方を考えて和を取れば良いです。

こっちのほうが実装が 100 倍楽ですね。

ll dp[55][55];
string s;

// [l, r)
ll dfs(int l, int r) {
    ll& ret = dp[l][r];
    if (ret >= 0) return ret;
    if (l==r) return ret = 1;
    ret = dfs(l+1, r);
    for (int i = l+1; i < r; i++) {
        if ((s[l] == '(' && s[i] == ')') || (s[l] == '[' && s[i] == ']')) {
            ret += dfs(l+1, i) * dfs(i+1, r);
        }
    }
    return ret;
}

class BracketSequenceDiv1 {
public:
    long long count(string s) {
        ::s = s;
        memset(dp, -1, sizeof(dp));
        return dfs(0, s.size()) - 1;
    }
};