题目描述
知识点
栈、字符串匹配
结果
实现
码前思考
- 看见子串匹配问题,我想到的是滑动窗口,但是很遗憾,我没有找到解决办法;
- 再然后看见最长,我想的是动态规划,毕竟是最优化问题嘛,但是也没有想清楚;
- 最后,我偷偷看了一下提示,才发现栈,原来之前也是做过括号匹配的题目的,用的就是栈,于是我就想怎么用栈来解决这个问题。
- 思路是这样的,既然是栈,那么当匹配好了一对’( )'之后,它们肯定就不在栈里面了,那么怎么保存它们的匹配信息呢?很容易想到就是设定一个数组
dp
,数组的元素dp[i]
表示目前i
后面最长的匹配子串(注意是目前),然后每次匹配成功之后就更新弹出栈顶之后的新栈顶的那个元素的dp
值; - 上面只是大概的思路,其实还有很多细节需要考虑清楚,例如:
- 如果字符串全部匹配,栈顶会为空,这怎么办?
- 需要将弹栈的元素的
dp
值加到新的栈顶的dp
值,还要再加2; - 等等,都需要通过手写模拟测试用例,认真分析得来的。
代码实现
//依然是采用栈的方式,只不过每次都要记录一个数据
//dp[i]表示i后面最长的匹配子串,不包含i
class Solution {
public:
int longestValidParentheses(string s) {
int size = s.size();
if(size == 0){ //特判
return 0;
}
//设置dp数组,初始化为0
vector<int> dp(size+1,0);
stack<int> st;
//首先压入一个-1,表示开始
st.push(-1);
//开始进行压栈操作
for(int i=0;i<size;i++){ //遍历每一个
//读入当前的字符
char cur = s[i];
//如果当前字符是'('
if(cur == '('){
//直接进行压栈
st.push(i);
}
//如果当前字符是右括号
if(cur == ')'){
//并且栈不为空而且栈顶是'('
if(st.top() != -1){
int topIdx = st.top();
char topChar = s[topIdx];
if(topChar == '('){
//说明匹配,那么需要进行弹出栈顶并且更新
st.pop();
dp[st.top()+1] = dp[topIdx+1] + 2 + dp[st.top()+1];
}else{
st.push(i);
}
}else{
st.push(i);
}
}
}
int ans = 0;
for(int i=0;i<=size;i++){
ans = max(dp[i],ans);
}
return ans;
}
};
码后反思
- 其实不用使用数组记录的,只要用左右数组下标相减就可以了!这个自己动手模拟一下,手写一下就出来:
//依然是采用栈的方式,只不过每次都要记录一个数据 //dp[i]表示i后面最长的匹配子串,不包含i class Solution { public: int longestValidParentheses(string s) { int size = s.size(); if(size == 0){ //特判 return 0; } stack<int> st; //首先压入一个-1,表示开始 st.push(-1); int ans = 0; //开始进行压栈操作 for(int i=0;i<size;i++){ //遍历每一个 //读入当前的字符 char cur = s[i]; //如果当前字符是'(' if(cur == '('){ //直接进行压栈 st.push(i); } //如果当前字符是右括号 if(cur == ')'){ //并且栈不为空而且栈顶是'(' if(st.top() != -1){ int topIdx = st.top(); char topChar = s[topIdx]; if(topChar == '('){ //说明匹配,那么需要进行弹出栈顶并且更新 st.pop(); ans = max(i-st.top(),ans); }else{ st.push(i); } }else{ st.push(i); } } } return ans; } };
需要注意设置-1
的巧妙之处!
2. 还可以用动态规划,还有一种更加巧妙地解法,这里就不提了。
参考文档
二刷代码
使用动态规划和栈进行解题即可
//见到最长就要想动态规划,这种最优解问题
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> st;
int len = s.size();
if(len == 0 || len == 1){
return 0;
}
//拼接一下
s='#'+s+'#';
vector<int> dp(s.size(),0);//初始化为1
st.push(0);
for(int i=1;i<s.size()-1;i++){
if(s[i]=='('){
st.push(i);
}else{
int idx = st.top();
if(s[idx]=='('){
st.pop();
int newIdx = st.top();
dp[newIdx] += dp[idx] + 2;
}else{
st.push(i);
}
}
}
int res=INT_MIN;
//然后进行求最大值
for(int i=0;i<s.size()-1;i++){
res=max(res,dp[i]);
}
return res;
}
};