本题的难点:刚开始想的话是想用栈匹配的方式来贪心的求解,后面发现"((())(()"这种形式的串贪心的话会将后面部分的算入答案中得到错误结果。那么问题就变成了一个递推式的问题,我们可以使用函数递归的思想来想,假设一个位置i处的左端左括号的数量已经大于右端,然而此时右端的答案并不能直接算进答案之中,因为不知道左端的括号是否能够全部被后面右端的右括号给匹配上,因此只有当左端最后一个括号被匹配上的时候,才能递归的处理左端之前已经匹配上的括号,时间复杂度大概是\(O(N^2)\),这是无法接受的=.=
此时应该用动态规划求解,\(dp[i]\)表示当前位置左端的最大合法匹配长度,易得"("处的值应该全部都是0,对于右括号,我们分为两种情况:
- 当\(s[i-1]\)为左括号的时候,我们可以知道此时刚好得到了一对新的匹配,所以此时的\(dp[i]=dp[i-2]+2\)
- 当\(s[i-1]\)为右括号的时候,如果\(s[i-1]\)处的右括号也有自己的匹配,我们此时就可以回溯到\(s[i-1]\)最大匹配长度的左端,也就是\(i-dp[i-1]-1\)处,如果此处符号为左括号,那么刚好和当前\(s[i]\)位置的右括号匹配上,我们可以新得到一段从\(i-dp[i-1]-1\)到\(i\)处的合法匹配。注意此时没有结束,假设\(i-dp[i-1]-1\)左端还有合法匹配呢?,所以此时得到新的递推方程\(dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]\)
代码如下
class Solution {
public:
int longestValidParentheses(string s) {
int n=s.size();
vector<int> dp(n+1,0);
int ans=0;
for(int i=1;i<n;i++){
if(s[i]==')'){
if(i>1&&s[i-1]=='(') dp[i]=dp[i-2]+2;
else if(i-dp[i-1]>0&&s[i-dp[i-1]-1]=='('){
dp[i]=dp[i-1]+2+((i-dp[i-1])>=2?dp[i-dp[i-1]-2]:0);
}
}
ans=max(ans,dp[i]);
}
return ans;
}
};