题目描述如下:
Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
For "(()"
, the longest valid parentheses substring is "()"
, which has length = 2.
Another example is ")()())"
, where the longest valid parentheses substring is"()()"
, which has length = 4.
一维简单动态规划,思想是:对S中从后向前的每个 ' ( ' ,我们来计算它最远对应到的那个‘)’的位置,在这两个字符中间的字符能够组成一个合法的括号串。
记当前 '(' 的下标为 i ,用idx[] 来保存每个i的最右合法匹配位置:
1. 如果它的右边是 ' ) ',那明显最远的合法匹配位置就到这个‘)’为止,idx[i] = i+1;
2.如果它的右边是 ' ( ',因为我们已经计算过它的最右合法匹配位置,在接着这个最右位置继续向右找 ;
3.如果右边不是 ‘( )’,则没有合法的匹配位置, idx = -1 ;
例子: 比如 s = " ( ) ( ( ( ) ) "
序号 0 1 2 3 4 5 6 7
( ) ( ( ( ( ) )
现在来计算idx的值;
1.从右向左找到第一个 ‘ ( ’,序号为5,右边是 ‘)’,匹配,所以 idx[ 5 ] = 6;
2.第二个s[4] ,右边是'(' ,它的匹配是6,所以跳到6再看右边,是‘)’,匹配,所以 idx[ 4 ] = 7;
3. 第三个s[3],右边是 '( " ,它的匹配是7,跳到7再看右边,越界,没有匹配,所以idx[3] = -1;
4.第四个s[2] ,右边是‘(’,但右边的‘(‘的idx为-1,即没有合法的匹配,所以s[2]自然也不能向右有合法匹配,idx[2]=-1;
5. s[0] = 1;
所以得到 idx 数组 :
序号 0 1 2 3 4 5 6 7
( ) ( ( ( ( ) )
idx 1 -1 -1 -1 7 6 -1 -1
现在可以计算最长合法长度了,计算很简单,见代码。
另外为了防止去判断越界,在原S两端添加了哨兵字符;
#define pb push_back #define vi vector<int> int longestValidParentheses(string s) { int sz=s.length(); if ( sz<=1 ) return 0; vector<char> SWithGuard(sz+2); vector<char>& swg=SWithGuard; //swg.reserve(sz+2); swg[0]=swg[sz+1]='#'; copy(s.begin(),s.end(),&swg[1]); vi idx(sz+2,-1); int i,j; for(i=sz+1;i>0;i--) { if (swg[i]=='(') { j=i+1; while(swg[j]=='('&&idx[j]!=-1) j=idx[j]+1; if (swg[j]==')') idx[i]=j; } } int longest=0; int cur=0; for(i=1;i<sz+2;) { if (idx[i]==-1) { longest=max(longest,cur); cur=0; i++; } else { cur+=idx[i]-i+1; i=idx[i]+1; } } return longest; }
这里描述了另一种有效的方法: http://www.cnblogs.com/remlostime/archive/2012/11/25/2787878.html