LeetCode_32
题目描述:
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
本题还有一个前置题目,详细内容可以点击此链接跳转 LeetCode_20,解决方案可以查看我的这篇CSDN博客 Li-Richard
稍微有点算法基础的同学看到本题时,脑海里第一个想法应该是使用DP来解决该问题,因为觉得应该可以用之前的结论推出后面一个结论,所以我们直接来讨论如何使用DP方法
比如一个字符串")()())",我们先写出对该字符串中以每一个字符为结尾的字符串的最长有效括号的长度
|字符串的每个字符| ) | ( | ) | ( | ) | ) |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
|字符串每个字符的位置| 0 | 1 | 2 | 3 | 4 | 5 |
|以相应字符结尾的最长有效括号的长度| 0 | 0 | 2 | 0 | 4 | 0 | |
(以下以len(i)表示i位置的最大有效括号字符串的长度)
在计算的过程中,如果位置i的字符为'(',则len(i)肯定为0(好好想想为什么)
此时你正在计算len(4),它是')',此时你首先应该看len(3),找到3-len(3)位置的字符看它是否为'(',若是则len(4)=len(3)+2
等等,我们好像算的不对,如果按照我们上面的算法len(4)应该等于2但实际情况应该等于4,我们好像忽略了什么。
再回到上面的分析,我们找到了3-len(3)的位置后,再往前看,len(3-len(3)-1)(意思为3-len(3)位置之前的字符的len)的值不为零,所以我们应该还要叫上这个位置的len,所以len(4)=len(3)+2+len(3-len(3)-1)(写程序时要注意数组下标不要越界)
所以初步的动态转移方程可以归纳为:
dp[i]=dp[i-1]+2+dp[i-1-dp[i-1]-1] (这只是初步的dp方程,没有判断s[i]和s[i-1-dp[i-1]]的情况)
代码如下:
int longestValidParentheses(string s)
{
if (s==""||s.length()==0||s.length()==1)
{
return 0;
}
int len = s.length();
vector<int>dp(len,0);
for (int i = 0; i < len; i++)
{
if (i==0)
{
dp[i] = 0;
}
else
{
if (s.at(i) == '(')
{
dp[i] = 0;
}
else
{
//重点在这
int pre = i - 1 - dp[i - 1];
if (pre >= 0 && s[pre] == '(')
dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);
}
}
}
sort(dp.begin(), dp.end());
return dp[len - 1];
}