193 最长有效括号
原题网址:https://www.lintcode.com/problem/longest-valid-parentheses/my-submissions
描述
'('
和')'
的字符串,找出其中最长的左右括号正确匹配的合法子串。
正确理解题目很重要……
比如对字符串“()((())”,最长有效括号子串为“(())”,输出应该是4
方法一:动态规划
设dp数组为以当前字符作为结尾的最长有效括号子串长度(注意dp[i]与dp[i-1]不是简单的累加关系,dp[i]也不是前i个字符串中最长有效括号长度),
所以如果当前字符是‘(’,dp值为0。如果当前字符是‘)’,有两种情况:
1.前一个字符是‘(’,前一个字符与当前字符刚好匹配,则dp[i] = dp[i - 2] + 2 ;
2.前一个字符是‘)’,这时要判断以前一个右括号为尾的最长有效括号之前的一个字符是否是左括号(,
如果是左括号,即“…((…))”,则dp[i]应该等于它和它对应左括号中间的有效括号数dp[i−1]加现在的两个,再加对应左括号之前的最长有效括号数dp[i−dp[i−1]−2],即dp[i]=dp[i−1]+dp[i−dp[i−1]−2]+2;
如果是右括号,即“…)(…))”,则dp[i]是0.
最后,因为dp[i]只是当前字符结尾的最长有效括号子串长度,所以需要用一个全局最长长度与每次更新的dp[i]对比。
注意数组越界的判断。
代码:
int longestValidParentheses(string &s) {
// write your code here
if(s.length()==0) return 0;
int maxLen = 0;
vector<int> dp(s.length(),0);
for(int i = 1; i < s.length(); i++)
{
if(s[i] == ')')
{
if(s[i-1] == '(')
{
dp[i] = i-2>=0?dp[i-2]+2:2;
}
else
{
if(i-dp[i-1]-1 >= 0)
{
if(s[i-dp[i-1]-1] == '(')
{
dp[i] = i-dp[i-1]-2>= 0? dp[i-1]+2+dp[i-dp[i-1]-2] : dp[i-1]+2;
}
}
}
}
if(dp[i] > maxLen)
{
maxLen = dp[i];
}
}
return maxLen;
}
方法二:
用两个计数器 left 和 right 。首先,从左到右遍历字符串,遇到 ‘(’,增加 left计数器;遇到 ‘)’ ,增加 right 计数器。每当 left 计数器与 right 计数器相等时,计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。如果 right计数器比 left 计数器大,将 left和 right 计数器同时变回 0。
代码:
int braketstr1(string s)
{
if (s.length() == 0 || s.length() == 1)
return 0;
int len = s.length();
int left = 0, right = 0;
int braketmax = 0;
for(int i=0;i<len;i++)
{
if (s[i] == '(')
left++;
else
right++;
if (right == left)
braketmax = braketmax > (2 * right) ? braketmax : 2 * right;
else if (right > left)
{
right = 0;
left = 0;
}
}
return braketmax;
}
参考:
1.https://blog.csdn.net/ysl_ysl123/article/details/93714147
2.https://www.cnblogs.com/ycw1024/p/11322099.html