Leetcode 32. 最长有效括号 dp


地址 https://leetcode-cn.com/problems/longest-valid-parentheses/

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:
输入:s = ""
输出:0
 

提示:
0 <= s.length <= 3 * 104
s[i] 为 '(' 或 ')'

解答
动态规划处理该题。
假设dp[i]表示从0~i的字符串以s[i]括号结尾能达到的最长括号子串的长度。
由于左括号需要查看后面的符号才能确认是否能括号配对
右括号是通过查看前面的符号就能确认能否配对,所以dp[i]有值的话 s[i]肯定是右括号 ')'

那么遍历字符串,如果当前是右括号则查看前一个符号是左括号还是右括号,不同情况不同处理
1 前一个符号是左括号

s[i]==')' s[i-1] == '('
那么dp[i]=2这时候继续查看s[i-2]是什么符号 看看这个匹配符号串能否继续增长
1.1 如果s[i-2]=='('  那么这个匹配符号串无法继续增长,本轮检测结束
1.2 如果s[i-2]==')' 这时候dp[i-2] 已经计算出以s[i-2]结尾的能达到到的最长括号子串的长度。
我们加上该长度即可
dp[i] += dp[i-2]

2 前一个符号也是右括号

s[i]==')' s[i-1] == ')'
那么我们查看向左延续dp[i-1]长度的符号能否找到一个右括号和s[i]匹配(也就是略过dp[i-1]的配对字符串)
假设dp[i-1]=x
2.1 如果s[i-x-1]==')'  那么就无法匹配 本轮检测结束
2.2 如果s[i-x-1]=='(' 可以与s[i]匹配  dp[i]=dp[i-1]+2  
这时候继续查看s[i-x-2]是什么符号 看看这个匹配符号串能否继续增长
效果同1.1 1.2

代码如下:


class Solution {
public:
	int longestValidParentheses(string s) {
		if (s.empty()) return 0;
		int dp[30010] = { 0 };
		for (int i = 0; i < s.size(); i++) {
			if (i > 0 && s[i] == ')') {
				//情况1
				if (s[i - 1] == '(') {
					dp[i] = 2;
					if (i>=2 && s[i - 2] == ')') {
						dp[i] += dp[i - 2];
					}
				}
				else if (s[i - 1] == ')') {
					//情况2
					int t = dp[i - 1];
					if ((i - 1 - t>=0) && s[i - 1 - t] == '(') {
						dp[i] = t + 2;
						if (i - 2 - t >= 0 && s[i - 2 - t] == ')') {
							dp[i] += dp[i - 2 - t];
						}
					}
				}
			}
		}
		int ans = -99;
		for (int i = 0; i < s.size(); i++) {
			ans = max(ans, dp[i]);
		}

		return ans;
	}
};

精简一点代码

class Solution {
public:
    void CanIncrease(int dp[],const string&s,int curr,int idx){
        if(idx>=0&& s[idx]==')'){ dp[curr] +=dp[idx];}
    }
	int longestValidParentheses(string s) {
		if (s.empty()) return 0;
		int dp[30010] = { 0 }; int ans = -1;
		for (int i = 0; i < s.size(); i++) {
			if (i > 0 && s[i] == ')'&& s[i - 1] == '(') {dp[i] = 2;CanIncrease(dp,s,i,i-2);}
			else if (i > 0 && s[i] == ')'&& s[i - 1] == ')') {
				//情况2
				int t = dp[i - 1];
				if ((i - 1 - t>=0) && s[i - 1 - t] == '(') {dp[i] = t + 2;CanIncrease(dp,s,i,i-2-t);}
			}
            ans = max(ans, dp[i]);
		}
		
		return ans;
	}
};

我的视频题解空间