• [Leetcode] 32.最长有效括号


    关键词:DP,动态规划,动规。

    最近在刷DP专栏的题目,这是其中一道题。

    给定一个只包含 '('')' 的字符串,找出最长的包含有效括号的子串的长度。

    longest-valid-parentheses

    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]) << "
    "
                 << endl;
    }
    
  • 相关阅读:
    ChinaCock界面控件介绍-CCLoadingIndicator
    delphi-search-path-vs-library-path-vs-browsing-path
    10.3制作Android Splash启动界面
    FMX取得屏分辨率
    REST easy with kbmMW #20 – OpenAPI and Swagger UI
    升级ChinaCock 10.3遇到的问题
    FastJson中的ObjectMapper对象的使用详解
    fastjson的值过滤器ValueFilter
    springboot 2.0 配置 spring.jackson.date-format 不生效
    War 包部署
  • 原文地址:https://www.cnblogs.com/sinkinben/p/11516742.html
Copyright © 2020-2023  润新知