题目两种解法:【转】http://blog.youkuaiyun.com/yapian8/article/details/28239003
求最长合法匹配的长度,这道题可以用一维动态规划逆向求解。假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。 dp[i]表示从s[i]到s[s.length - 1]包含s[i]的最长的有效匹配括号子串长度。则存在如下关系:
- dp[s.length - 1] = 0;
- i从n - 2 -> 0逆向求dp[],并记录其最大值。若s[i] == '(',则在s中从i开始到s.length - 1计算dp[i]的值。这个计算分为两步,通过dp[i + 1]进行的(注意dp[i + 1]已经在上一步求解):
- 在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,其下标为j = i + 1 + dp[i + 1]。若j没有越界,并且s[j] == ‘)’,则s[i ... j]为有效括号匹配,dp[i] =dp[i + 1] + 2。
- 在求得了s[i ... j]的有效匹配长度之后,若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1]。
- class Solution {
- public:
- int longestValidParentheses(string s) {
- int len = s.length();
- if(len<2)
- return 0;
- int max = 0;
- int *dp = new int[len];
- for(int k = 0;k<len;k++)//把辅助数组清空,存储为0
- dp[k] = 0;
- for(int i = len-2;i>=0;i--)
- {
- if(s[i] == '(')//只对左括号处理,右括号在数组中存储为0
- {
- int j = i+1+dp[i+1];//计算与当前左括号匹配的右括号的位置。可能存在也可能不存在
- if(j<len && s[j] == ')')//确保位置不能越界
- {
- dp[i] = dp[i+1] + 2;//找到了相匹配的右括号,当前数组中存储的最长长度是它后一个位置加2,后一个位置可能存储长度是0
- if(j+1<len)//这是连接两个子匹配的关键步骤
- dp[i] += dp[j+1];//在j的后面可能已经存在连续的匹配,要记得加上。dp[j+1]存储了以j+1开始的匹配
- }
- if(dp[i]>max)
- max = dp[i];//更新最长长度
- }
- }
- return max;
- }
- };
一维简单动态规划,思想是:对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
转载自:【】http://www.cnblogs.com/remlostime/archive/2012/11/25/2787878.html
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.
1 struct Node 2 { 3 char c; 4 int index; 5 Node(){} 6 Node(char _c, int idx):c(_c), index(idx){} 7 }; 8 9 class Solution { 10 public: 11 int longestValidParentheses(string s) { 12 // Start typing your C/C++ solution below 13 // DO NOT write int main() function 14 stack<Node> st; 15 st.push(Node(')', -1)); 16 int ret = 0; 17 for(int i = 0; i < s.size(); i++) 18 { 19 char c = s[i]; 20 if (c == '(') 21 st.push(Node(c, i)); 22 else 23 { 24 Node node = st.top(); 25 if (node.c == '(') 26 { 27 st.pop(); 28 ret = max(ret, i - st.top().index); 29 } 30 else 31 st.push(Node(c, i)); 32 } 33 } 34 35 return ret; 36 } 37 };