Leetcode 32 - Longest Valid Parentheses(线性dp)

来源:互联网 发布:深圳赛维网络董事长 编辑:程序博客网 时间:2024/06/11 07:25

题意

给定一个括号序列,求其中合法的最长括号序列的长度

思路

很久以前做过一道类似的题,是用区间dp,O(n3)的时间复杂度过的,这道题O(n)的线性dp就可以了。

状态表示d[i],以元素s[i]作为起点的最长括号序列。

其实我们的括号序列无非就这两种情况的嵌套:()()和(())。根据以上的状态表示我们列出对应的d[]数组:

( ) ( )

4 0 2 0

( ( ) )

4 2 0 0

当我们开始处理s[i]时,若s[i]==),d[i]肯定为0。

关键就是左括号:

首先,我们需要找到需要和当前左括号匹配的那个括号的位置,我们记那个括号的位置是nm(need_to_match),计算可得:nm=i+1+d[i+1]

nm的得出:d[i + 1]为我们的s[i + 1]匹配的括号长度,即从i + 1开始,走过d[i + 1]的序列是已经匹配过的,所以需要和我们s[i]匹配的位置nm==i+1+d[i+1]

当我们得到nm后,因为s[i] == (,若s[nm] == ),则d[i] = 0。

不然,我们的s[nm] == ),即s[i]和s[nm]是匹配的。

首先,d[i] = d[i + 1] + 2(d[i + 1]为s[i + 1]匹配的括号长度,我们需要在i + 1的基础上叠加上当前匹配的())。

然后,我们还要考虑这样一种情况,就nm + 1之后匹配的长度我们也要叠加上,因为我们d[i]表示的是从i开始的满足条件的括号序列的长度,则i到nm是满足条件的,我们还需要加上nm+1满足条件的那段序列(即可以考虑这样一种情况:(())())。所以此时d[i]还要叠加上d[nm + 1]。(可以参考一道类似的题: HDU1506-Largest Rectangle in a Histogram(dp) )。

转移方程

  1. s[i]==):d[i] = 0;

  2. s[i]==(:

    nm=i+1+d[i+1]

    1. s[nm]==):d[i]=d[i+1]+2,且若nm+1<nd[i]+=d[nm+1]nm<n
    2. s[nm]==(:d[i]=0nm<n

时间复杂度O(n)

空间复杂度O(n)

代码

const int maxn = 100000 + 5;int d[maxn];class Solution {public:    int longestValidParentheses(string s) {        memset(d, 0, sizeof(d));        int n = s.length(), res = 0;        if (n == 0) return 0;        d[n - 1] = 0; //init, the last element is 0        for (int i = n - 2; i >= 0; i--) {            if (s[i] == ')') d[i] = 0;            else {                int nm = i + 1 + d[i + 1]; //the position that current element need to match                if (nm < n && s[nm] == ')') {                    d[i] = d[i + 1] + 2;                    int nxt = nm + 1;                    if (nxt < n) d[i] += d[nxt];                }            }            res = max(res, d[i]);        }        return res;    }};
0 0
原创粉丝点击