POJ2955 Brackets 題解 區間DP

題目連接:http://poj.org/problem?id=2955
【題目描述】
《規則的括號序列》
咱們定義一個字符串序列爲「規則的括號序列」當且僅當它知足以下條件:
一、空字符串是規則的括號序列;
二、若是字符串 s 是一個規則的括號序列,那麼 (s) 和 [s] 也是規則的括號序列;
三、若是字符串 a 和 b 都是規則的括號序列,那麼 ab 也是規則的括號序列;
四、除此以外的字符串都不能稱爲規則的括號序列。
舉個例子,下面的這些字符串都是規則的括號序列:
(), [], (()), ()[], ()[()]
與此同時,下面的這些字符串都不是規則的括號序列:
(, ], )(, ([)], ([(]
給你一個字符串 a1a2...an,你的任務是找到它的最長的一個知足「規則的括號序列」條件的子序列,並輸出該最長規則括號子序列的長度。也就是說,你須要找到最長的一組下表i1,i2,...,im,他們知足1≤i1<i2<...<im≤n,同時ai1aid...aim是規則的括號序列。
好比,給你一個字符串 ([([]])] ,它的最長規則的括號子序列是 [([])]。
【輸入格式】
輸入包含多組樣例。每組樣例佔據一行,包含一個字符串,該字符串僅由 (,),[,]組成。字符串的長度在1到100之間。
輸入數據的最後一行包含一個字符串「end」用於標識文件結束。
【輸出格式】
對於每一組數據(除了最後的「end」),你須要輸出它的最長規則的括號子序列的長度。
【樣例輸入】
((()))
()()()
([]])
)[)(
([][][)
end
【樣例輸出】
6
6
4
0
6
【題目分析】
涉及的知識點:區間動態規劃(區間DP)。
爲了方便起見,咱們這裏將「最長規則的括號序列」簡稱爲「目標序列」。
咱們用 dp[L][R] 表示 字符串 s 的子串 s[L..R] ,那麼:
· 首先咱們要肯定,若是字符串 s 是空串,或者它的長度爲1,那麼它的目標序列的長度確定是 0 ;
· 若是字符串 s 的長度爲2, 那麼當 s=="()" 或者 s=="[]" 的時候,它的目標序列的長度就是它自己的長度——2;不然,它的目標序列的長度爲0。
· 當 s[L]=='(' 而且 s[R]==')' 或者 s[L]=='[' 而且 s[R]==']' 的時候, dp[L][R] 的一種備選方案(稱爲第1中備選方案)是 dp[L+1][R-1] + 2;
· 不過 (s') 或者 [s'] (這裏 s' 用於表示 s[L+1 .. R-1] 的目標序列)條件不必定是成立的,因此任何條件下都成立的一種備選方案(稱爲第2種備選方案)是 max(dp[L+1][R], dp[L][R-1]) ,即咱們剔除掉最左邊的字符串,或者最右邊的字符串所可以帶來的效果;
· 還有一種狀況是字符串 s[L..R] 是兩個字符串拼接而成的,那麼這種狀況下,它的一種備選方案(稱爲第3種備選方案)是 max(dp[L][i] + dp[i+1][R]) ,其中 L+1≤i<R-1。
而後咱們發現還能夠合併第2種備選方案到第3中備選方案中,由於 max(dp[L+1][R], dp[L][R-1]) 其實就等於 max(dp[L][i] + dp[i+1][R]) ,其中 i=L或R-1。
因此第2及第3中備選方案合併到一塊兒就是 max(dp[L][i] + dp[i+1][R]) ,其中 L≤i<R。
據此,咱們能夠編寫代碼以下: ios

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int maxn = 101;
int n, dp[maxn][maxn];
string s;

int main() {
    while ((cin >> s) && s != "end") {
        fill(dp[0], dp[0]+maxn*maxn, 0);
        n = s.length();
        for (int l = 2; l <= n; l ++) {
            for (int i = 0; i+l-1 < n; i ++) {
                int j = i + l - 1;
                if (s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
                    dp[i][j] = (l > 2 ? dp[i+1][j-1] : 0) + 2;
                for (int k = i; k < j; k ++)
                    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j]);
            }
        }
        cout << dp[0][n-1] << endl;
    }
    return 0;
}
相關文章
相關標籤/搜索