现在的位置: 首页 > 综合 > 正文

longest valid parentheses

2017年11月11日 ⁄ 综合 ⁄ 共 1610字 ⁄ 字号 评论关闭

题目描述如下:

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

 

抱歉!评论已关闭.