題目詳情
給定一個只包含 '(' 和 ')' 的字符串,找出最長的包含有效括號的子串的長度。
示例 1:
輸入: "(()"
輸出: 2
解釋: 最長有效括號子串爲 "()"
示例 2:
輸入: ")()())"
輸出: 4
解釋: 最長有效括號子串爲 "()()"
——題目難度:困難
分析
題目所說的 “最長的包含有效括號的子串” 的意思是該子串裏不允許有 沒有成爲"(...)",也就是沒有匹配的括號。
使用動態規劃解題一般有如下3個步驟:
- 確定狀態
- 研究最優策略的最後一步
- 化爲子問題 - 確定狀態轉移方程
- 根據子問題定義得到 - 確定邊界條件 和 初始情況
接下來用以上3個步驟來分析題目:
1.確定狀態:這裏定義一個dp數組,dp[i]表示以下標 i 爲字符結尾的最長有效字符串的長度(注意:這裏是必須將s[i]這個字符包含在內的!)
2.確定狀態轉移方程:當遍歷s串時,如果是s[i]='(',就不用考慮,因爲不可能構造合法括號;
當s[i]=')'時,分以下兩種情況:
①s[i-1]='('時,也就是字符串形如"...()",那麼dp[i] = dp[i-2] + 2
②s[i-1]=')'時,也就是字符串形如"...))"的時候,這種情況下,如果前面要和 s[i] 組成有效括號對的字符,即形如"( (....) )",這樣的話,就要求 s[i - 1] 位置必然是有效的括號對,否則 s[i] 無法和前面對字符組成有效括號對。
如果倒數第二個')'是一個有效字符串(記爲subs),那麼我們只需要判斷 subs 前面的一個符號是不是'(',如果是'(' 則可以說明 此時的最長有效括號的長度爲:subs 的長度(dp[i-1]) 加上字符串 subs 前面的有效字符串(dp[i - dp[i - 1] - 2]) 加上 2,這時候字符串可以形如"(...)((...))" 。
3.確定邊界條件 和 初始情況:
- i-2 有可能小於0而導致越界,這時候就是隻有(),前面記爲0就好了
- i - dp[i - 1] - 2 和 i - dp[i - 1] - 1 都有可能出現小於0的越界問題,如果越界了 同樣 記爲0即可
-解題代碼
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.size();
int ans = 0;
vector<int> dp(len);
for(int i = 1; i < len; i++)
{
if (s[i] == ')') {
if (s[i-1] == '(') {
dp[i] = (i - 2 >= 0 ? dp[i-2] : 0) + 2;
} else if (i - dp[i-1] - 1 >= 0 && s[i-dp[i-1]-1] == '(') {
dp[i] = (i - dp[i-1] - 2 >=0 ? dp[i-dp[i-1]-2] : 0) + dp[i-1] + 2;
}
}
ans = max(ans, dp[i]);
}
return ans;
}
};
結果