class Solution { public: int longestValidParentheses(string s) { int res = 0; //长度为0的串,返回0 if(s.length() == 0) return res; //dp[i]表示以下标为i的字符为结束点的最长合法括号长度 vector<int> dp(s.length(), 0); //第一位不管是左括号还是右括号都是0,因此不用管 for(int i = 1; i < s.length(); i++){ //取到左括号记为0,有右括号才合法 if(s[i] == ')'){ //情况一:如果该右括号前一位就是左括号 if(s[i - 1] == '(') //计数+2 dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2; //情况二:找到这一段连续合法括号序列前第一个左括号做匹配 // 如果 ()) 则 i - dp[i - 1] == 0 // i - dp[i - 1] > 0 说明i-1为 右括号,且i-1属于一段合法序列,其长度为dp[i-1],如()()(()) i==7时,dp[6]=2; // i-dp[i-1]-1为前一段合法序列再前一个元素下标,即与 i 对应的下标; else if(i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') // dp[i - 1] > 1 说明dp[i-1]为合法序列,情况为()()(()); // dp[i - 1] <= 1 说明dp[i-1]为合法序列,情况为()(),i=3时,dp[2]=2,则相减结果为1; ()),i=3时,dp[2]=2, i-dp[i-1]为0; // i - dp[i - 1] > 1 ,此处先执行i-dp[i-1],再判断结果是否>1; // 则dp[i - dp[i - 1] - 2]为dp[i-1]这段合法序列长度的再前两个位置的dp值,注意i - dp[i - 1] - 1是跟当前 i对应的左括号, 该位置再-1则为对应左括号前一位; dp[i] = (i - dp[i - 1] > 1 ? dp[i - dp[i - 1] - 2] : 0) + dp[i - 1] + 2; } //维护最大值 res = max(res, dp[i]); } return res; } }; // class Solution { // public: // int longestValidParentheses(string s) { // int res = 0; // //记录上一次连续括号结束的位置 // int start = -1; // stack<int> st; // for(int i = 0; i < s.length(); i++){ // //左括号入栈 // if(s[i] == '(') // st.push(i); // //右括号 // else{ // //如果右括号时栈为空,不合法,设置为结束位置 // if(st.empty()) // start = i; // else{ // //弹出左括号 // st.pop(); // //栈中还有左括号,说明右括号不够,减去栈顶位置就是长度 // if(!st.empty()) // res = max(res, i - st.top()); // //栈中没有括号,说明左右括号行号,减去上一次结束的位置就是长度 // else // res = max(res, i - start); // } // } // } // return res; // } // };