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;
}
};
20240911
/*
* @lc app=leetcode.cn id=32 lang=cpp
* @lcpr version=30204
*
* [32] 最长有效括号
*/
// @lcpr-template-start
using namespace std;
#include <algorithm>
#include <array>
#include <bitset>
#include <climits>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <queue>
#include <stack>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <cstring>
// @lcpr-template-end
// @lc code=start
class Solution {
public:
int dp[30010];
int longestValidParentheses(string s) {
s.insert(0,"#"); memset(dp,0,sizeof dp);
int ans =0;
for(int i= 2;i < s.size();i++){
if(s[i]==')'){
if(s[i-1]=='('){
dp[i]=2+dp[i-2];
}else{
int len = dp[i-1];
if(s[i-len-1]=='('){
dp[i] = dp[i-1]+2+dp[i-len-1-1];
}
}
}
ans = max(ans,dp[i]);
}
return ans;
}
};
// @lc code=end
/*
// @lcpr case=start
// "(()"\n
// @lcpr case=end
// @lcpr case=start
// ")()())"\n
// @lcpr case=end
// @lcpr case=start
// ""\n
// @lcpr case=end
*/
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
![阿里打赏](https://files.cnblogs.com/files/itdef/ali2.bmp)
![微信打赏](https://files.cnblogs.com/files/itdef/weixin2.bmp)