标签:long 转移 就是 别人 需要 ret 代码 情况 cas
题目描述:
给定一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
解题思路:
这个题我一开始也想到用动态规划去解决,不过状态转移方程没有找对,试了几种都是错的。最后无奈看了题解,发现题解的思路真的很巧妙。所以偶尔看一看别人的思路,学习别人优秀的想法,真的可以收获很多。
dp的思路是:1)dp[i]表示,下标i为结尾的序列中,最长有效括号子串的长度。2)如果s[i]是‘(’,那么显然无法构成一个有效的序列,所以dp[i]为0,如果s[i]是‘)’,那么就需要联系前一个字符,来进行状态转换。3)如果s[i-1]是‘(’,那么s[i-1]和s[i]构成一对,所以这时只需要用dp[i-2]加上2即可。如果s[i-1]是‘)’,那么就需要判断以s[i-1]为结尾的有效子串的前一个字符是不是‘(’,如果是的话,dp[i]的值就等于dp[i-1]加上2再加上dp[i - dp[i-1] - 2]。
最后一种情况相对难以理解,再解释一下就是:把s[i-1]为结尾的有效子串看成一个整体,这个整体的前一个字符如果是‘(’,就刚好可以和s[i]的‘)’组成一对,所以长度就变成s[i-1]结尾的子串长度加二。但是这样是不够的,如果现在这个加2以后子串前面正好还有有效子串,那么这两个子串就可以组成一个更长的有效子串,这就是最后加上dp[i - dp[i-1] - 2]的原因。
代码如下:
class Solution { public: int longestValidParentheses(string s) { // 保存下标i为结尾的序列中,最长有效括号子串的长度 vector<int> dp(s.size()); int ret = 0; for (int i = 1; i < s.size(); ++i) { if (s[i] == ‘(‘) { dp[i] = 0; } else if (s[i - 1] == ‘(‘) { if (i == 1) dp[i] = 2; else dp[i] = dp[i - 2] + 2; } else { // case : (s[i - 1] == ‘)‘) if (i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] - 1] == ‘(‘) if (i - dp[i-1] - 2 < 0) dp[i] = dp[i-1] + 2; else dp[i] = dp[i-1] + 2 + dp[i - dp[i-1] - 2]; } ret = max(ret, dp[i]); } return ret; } };
32.最长有效括号(Longest Valid Parentheses)
标签:long 转移 就是 别人 需要 ret 代码 情况 cas
原文地址:https://www.cnblogs.com/yxsrt/p/12864863.html