• 动态规划——Longest Valid Parentheses


    Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

    Example 1:

    Input: "(()"
    Output: 2
    Explanation: The longest valid parentheses substring is "()"
    

    Example 2:

    Input: ")()())"
    Output: 4
    Explanation: The longest valid parentheses substring is "()()"
    

    大概意思就是,提供一个只含'('和')'的字符串S,请在S中找到一个'('和')'配对出现的最长连续子字符串,输出其长度这个最长连续子字符串可以是“(())”这种,也可以是“()()”这种,而且必须是连续的。
    这个题的状态相对来说比较好想,状态dp[i]:包含第i个字符的最长连续子串的长度,前提是包含当前这个字符S[i](因为要保证结果是个连续的字串),所以可以想像到所有'('处的dp值都是0。这样问题就来了
    状态转移方程是什么呢?考虑到'('和')'要配对,不妨两个两个的看S的字符。仔细研究所有字符串的情况可以发现,所有符合要求的无非就两种情况:(1)...().... (2)...((...))...两个两个的看S的字符,
    (1)(2)中没有包含的连续的两个字符的情况不用考虑,像什么S[i]=='('和S[i-1]==')'之类的,都不用管,没用!
    对于情况一,即S[i]==')'和S[i-1]=='('这种直接配对的情况,直接dp[i] = dp[i-2]+2,道理不赘述,注意数组访问不要越界
    对于情况二,稍稍复杂一些,这种情况就是大的套小的,我们要查看小套的上界,也就是大套的左边是不是'(',如何访问这个大套的左侧字符呢,认真思考后可以想到dp[i-1]代表包含了S[i-1]的最长连续子串的长度,S[i]
    是大套的右边界')',S[i-1]是小套的右边界')',则S[i-dp[i-1]]是小套的左边界,(当然这个dp[i-1]等于0也就不用管了没意义的),易知S[i-dp[i-1]-1]是大套的左边界,如果S[i-dp[i-1]-1]='('说明能配对,同时要注意
    到dp[i-dp[i-1]-1]可能不等于0,也就是说大套的左侧可能还有符合要求的字串,如果存在的话应该连起来,所以这种情况下dp[i] = dp[i-1]+dp[i-dp[i-1]-2]+2,即小套长度+大套左侧的长度+套左右边界两个字符的长度2;
    如果S[i-dp[i-1]-1]=')'说明不能配对,此时不管用了,让dp[i]保持默认值0即可。当然这种情况也要注意数组访问不能越界!

    此题还有设置一个变量ans来记录最长的这个长度,因为S中可能断断续续有好几个离散的符合要求的'('和')'配对的字串,需要这个变量ans来不断筛选最优解,操作很简单,每次求出一个dp[i],就更新一次ans的值,
    即:ans = ans > dp[i]?ans:dp[i]

    代码如下:

     1 int longestValidParentheses(string s) {
     2             int ans = 0;
     3     int slen = s.length();
     4     if (slen <= 1)return ans;
     5     int* dp = new int[slen];
     6     for (int i = 0; i < slen; i++)
     7         dp[i] = 0;
     8     if (s[0] == '('&&s[1] == ')')dp[1] = 2;
     9     ans = dp[1];
    10     for (int i = 2; i < slen; i++){
    11         if (s[i] == ')'){
    12             if (s[i - 1] == '(')dp[i] = dp[i - 2] + 2;
    13             else{
    14                 if ((i - dp[i - 1] - 1) == 0 && s[i - dp[i - 1] - 1] == '(')dp[i] = dp[i - 1] + 2;
    15                 else if ((i - dp[i - 1] - 1) > 0 && s[i - dp[i - 1] - 1] == '(')dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
    16             }
    17         }
    18         ans = ans > dp[i] ? ans : dp[i];
    19     }
    20     delete[]dp;
    21     return ans;
    22 }












  • 相关阅读:
    安装redis报错 you need tcl 8.5 or newer in order to run redis test
    wm_concat函数oracle 11g返回clob
    ArrayList去重
    虚拟机linux下安装tomcat外部可访问
    虚拟机下Linux安装jdk
    本地硬盘和虚拟机之间复制文件
    VMware中为Linux安装vm-tools
    windows操作系统下载tomcat,并与eclipse进行整合
    Windows配置java运行环境的步骤
    Mac配置java运行环境的步骤
  • 原文地址:https://www.cnblogs.com/messi2017/p/9879807.html
Copyright © 2020-2023  润新知