标签:第一个 数组下标 解法 语句 == 输入 就是 i++ 规划
关键词:DP,动态规划,动规。
最近在刷DP专栏的题目,这是其中一道题。
给定一个只包含 ‘(‘
和 ‘)‘
的字符串,找出最长的包含有效括号的子串的长度。
Sample1
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
Sample2
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
对于DP嘛,首先还是需要抽象出状态函数:
dp[i] 表示:以 S[i] 结尾的,最长有效括号串的长度。
然后是状态转移方程:
如果 s.len == 0 or s.len == 1,那么返回 0 .
否则:
if s[i]=='(' then dp[i]=0
if s[i]==')' then:
if s[i-1]='(' then dp[i] = dp[i-2] + 2 (数组下标是否越界,即 i>=2? )
if s[i-1]=')' then:
if s[i-dp[i-1]-1] == '(' then dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2 (是否越界?)
if s[i-dp[i-1]-1] == ')' then dp[i] = 0
第一个 if
语句表示:形如 ....(
这样的字符串,是必然不合法的。
第二个 if
语句表示:形如 ....)
这样的字符串,这样我们需要考虑 s[i-1]
:
s[i-1]=‘(‘
: 字符串形如 ...()
,显然,下标对应如下:
i-2 i-1 i
x ( )
显然,dp[i]
的值应当是 dp[i-2] + 2
。
s[i-1]=‘)
: 字符串形如 ...))
,显然,下标对应如下:
? i-1 i
x (... ) )
现考虑与 s[i-1]
匹配的 左括号的位置,s[i-1]=‘)‘
,其合法的括号串长度是 dp[i-1]
,那么 ‘(‘
的位置应当是:
i - 1 - (dp[i-1] - 1) = i - dp[i-1]
也就是说,s[i] = )
匹配的左括号位置应当是:i - dp[i-1] - 1
.
i-dp[i-1]-1 i-dp[i-1] i-1 i
x ( ... ) )
如果 x = s[i-dp[i-1]-1] == )
,那么: dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2
(因为 “ 没画出来的 ” 前面仍有可能是有效的括号串)
但是如果 i-dp[i-1]-1
这个位置的符号不是 (
呢?这就说明以 s[i]
为结尾的括号传不是合法的,即:d[i] = 0
。
完整代码:
需要特别注意数组下标越界的问题,一旦越界,说明前面不是一个有效的括号串。
/*
DP解法:
dp[i] 表示:以s[i]结尾的,最长有效子串
那么:
if s[i]=='(' then dp[i] = 0
if s[i]==')':
if (s[i-1]=='(') then dp[i] = dp[i-2]+2
if (s[i-1]==')') then dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2
*/
#include "leetcode.h"
#include <stack>
class Solution
{
public:
int longestValidParentheses(string s)
{
int len = s.length();
if (len == 0 || len == 1)
return 0;
vector<int> dp(len, 0);
for (int i = 1; i < len; i++)
{
if (s[i] == ')')
{
if (s[i - 1] == '(')
{
if (i >= 2)
dp[i] = dp[i - 2] + 2;
else
dp[i] = 2;
}
else if (s[i - 1] == ')')
{
int midlen = dp[i - 1];
if (i >= (midlen + 1))
{
char c = s[i - midlen - 1];
if (c == '(')
dp[i] = dp[i - 1] + 2 + (i >= (midlen + 2) ? dp[i - midlen - 2] : 0);
else
dp[i] = 0;
}
else
{
dp[i] = 0;
}
}
}
}
for (int x : dp)
cout << x << ' ';
cout << endl;
int result = -1;
for (int x : dp)
result = max(result, x);
return result;
}
};
int main()
{
string s[] = {"())", "(()", ")()())"};
Solution sol;
for (int i = 0; i < 3; i++)
cout << sol.longestValidParentheses(s[i]) << "\n"
<< endl;
}
标签:第一个 数组下标 解法 语句 == 输入 就是 i++ 规划
原文地址:https://www.cnblogs.com/sinkinben/p/11516742.html