问题描述:
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”
问题分析:
用数组dp[i]表示括号串s[i]结尾的最大括号字串长度。
当 s[ i ] 是’ ( '时, dp[i]一定为0。
当s[ i ]为‘ ) ‘时,判断s[i-1]是否为‘( ’
s[i-1]==’(’ :
则dp[i] = dp[i-2]+2 (i-2)>=0。dp[i]=2, (i-2)<0。
s[i-1]!=’('
此时判断s[i-1-dp[i-1]] 是否为’(’
类似于 (()()), s[i-1-dp[i-1]]其实就是s[i]前面第一个不在有效子串中的括号
应注意需要[i-1-dp[i-1]>=0
如果s[i-1-dp[i-1]]==’ ( ’
dp[i] = dp[i-1]+2 +dp[i-1-dp[i-1]-1] ; (i-1-dp[i-1]-1)>0
dp[i] = dp[i-1]+2 ; (i-1-dp[i-1]-1)<=0
类似于 ()(()()) 最后一个在4的基础上+2后应该加上最前面的两个, 所以 在s[i-1]的基础上加2后 应该加上dp[i-1dp[i-1]-1] 。
其它情况下dp[i]=0;
过程:
if(s[i]='(') dp[i] = 0; else { if(s[i-1]=='('){ if((i-2)>0) dp[i]= dp[i-2]+2; else dp[i] = 2; } else{ if((i-1-dp[i-1])>=0&&s[i-1-dp[i-1]]=='(') { if(i-1-dp[i-1]-1>0) dp[i] = dp[i-1]+2+ dp[i-1-dp[i-1]-1]; else dp[i] = dp[i-1]+2; } else dp [i]=0; } }
代码:
package DP;
/*
最长有效括号
*/
public class L32 {
public static int longestValidParentheses(String s){
int dp[] = new int [s.length()];
if(s==null||s.equals(""))
return 0;
int max= 0 ;
dp[0]=0;
for(int i=1;i<s.length();i++){
if(s.charAt(i)=='(') //最后一个字符是“(”
dp[i]=0;
else{ // 最后一个字符是") "
if(s.charAt(i-1)=='(') {
if (i - 2 > 0)
dp[i] = dp[i - 2] + 2;
else
dp[i] = 2;
}
else{
if((i-1-dp[i-1]>=0)&&s.charAt(i-1-dp[i-1])=='('){
if(i-1-dp[i-1]-1>0){
dp[i] = dp[i-1]+2+dp[i-1-dp[i-1]-1];
}
else{
dp[i]= dp[i-1]+2;
}
}
else{
dp[i]=0;
}
}
}
max = max>dp[i]?max:dp[i];
}
return max;
}
public static void main(String[] args) {
String s = "((()))";
System.out.print(longestValidParentheses(s));
}
}