区间dp,给一个括号序列,求最长的合法的子序列的长度。
dp[i][j]表示[i,j]这段区间里面的最长子序列的长度,当s[i] =s[j] 是,可以转换位子问题:求[i+1,j-1]的最长合法子序列的长度,但是不能就直接求得,如 [][] , 可知答案应为4,但如果直接求得话就是2。
所以不管s[i] 和s[j] 是否相等,都要枚举中间得元素。
区间dp写成记忆化得时候一定要处理好边界情况。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char a[110];
int len,d[101][101];
bool match(int i,int j){
return ((a[i]=='('&&a[j]==')')||(a[i]=='['&&a[j]==']'));
}
int dp(int i,int j){
int & ans = d[i][j];
if(ans != 1e9) return ans;
if(i+1 == j) return (ans = match(i,j)?2:0);
ans = 0;
if(match(i,j)) ans = max(ans,dp(i+1,j-1)+2);
for(int k = i;k<j;k++)
ans = max(ans,dp(i,k)+dp(k+1,j));
return ans;
}
int main(){
while(scanf("%s",a)&&strcmp(a,"end")){
len = strlen(a);
for(int i = 0;i<len;i++) for(int j = 0;j<len;j++) d[i][j] = 1e9;
printf("%d\n",dp(0,len-1));
}
return 0;
}