问题:
给定由 "(" 和 ")" 构成的字符串,
求其中完全匹配的子串,最长长度为多少。
Example 1: Input: s = "(()" Output: 2 Explanation: The longest valid parentheses substring is "()". Example 2: Input: s = ")()())" Output: 4 Explanation: The longest valid parentheses substring is "()()". Example 3: Input: s = "" Output: 0 Constraints: 0 <= s.length <= 3 * 104 s[i] is '(', or ')'.
解法:DP(动态规划)
1.确定【状态】:字符串s的
- 第i个字符:s[i]
2.确定【选择】:分两种情况
- s[i] == '(':
- 任何以'('为结尾的字符串,都不可能是匹配字符串,因此:dp[i]=0
- s[i] == ')':
- 若前面串中存在多余出来的 '(' (open>0)那么这里匹配到一对括号:dp[i]=dp[i-1]+2
- 同时,若此时dp[i]得到的匹配子串长度<子串总长度 i,需要追加前面的匹配结果:dp[i]+=dp[i-dp[i]]
- 解释:到当前为止的字符串:s[ 0 ~ i-dp[i] ~ i ]
- 在当前直前的子串 i-dp[i] ~ i 中,我们已得到结果:dp[i]=dp[i-1]+2
- 在这再前一个子串 0 ~ i-dp[i] 中,若有匹配好的(以i-dp[i]为结尾的)子串,我们则须将这一段也追加入当前结果中:dp[i]+=dp[i-dp[i]]
3. dp[i][j]的含义:
字符串s,到第 i 个字符为止,包含最后一个字符s[i]在内,最长匹配子串的长度。
4. 状态转移:
dp[i]=
- (s[i] == '('):= 0 (open++) (s[i] == ')') && open>0:=
- 上一个包含s[i]字符的状态:dp[i-1]+2
- + 当前满足条件子串直前的字符串的结果 dp[i-dp[i]]
- (open--)
5. base case:
- dp[0]=0
- dp[1]=0
对于本问题所求,则将以各个字符(包含该字符)为止,最长满足条件匹配子串长度,求最大值。
res = max(res, dp[i]);
代码参考:
1 class Solution { 2 public: 3 //dp[i]: s[0~i], && s[i]included, the length of the parentheses substring. 4 //state: index i 5 //opt: 6 // s[i]=='(': dp[i]=0 (against:&& s[i]included) 7 // s[i]==')': if opened(previous contained "("), dp[i]=dp[i-1]+2 8 // if dp[i](substring len)< i(all str len), dp[i]+=dp[i-dp[i]]; add previous result 9 //base: dp[0] = 0, 10 // dp[1] = 0 11 int longestValidParentheses(string s) { 12 int res = 0; 13 int open = 0; 14 vector<int> dp(s.size(), 0); 15 for(int i=0; i<s.size(); i++) { 16 if(s[i]=='(') { 17 open++; 18 dp[i]==0; 19 } else if(s[i]==')' && open>0) {//')' 20 open--; 21 dp[i] = dp[i-1]+2; 22 if(dp[i]<i) dp[i]+=dp[i-dp[i]]; 23 } 24 res = max(res, dp[i]); 25 } 26 return res; 27 } 28 };