1. 程式人生 > 實用技巧 >193 最長有效括號

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