题意:给一个括号序列,问包含此序列的最短合法括号序列;
解法:普通的区间dp,num[i][j]记录的是i-j子序列最少需要补充的括号个数,只是在要记录区间的最优分界点rem[i][j]从而将最短合法括号序列输出,复杂度O(n^3);
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
char s[2004];
int num[2004][2004];
int rem[2004][2004];
int len;
bool OK(char a,char b)
{
if((a=='('&&b==')')||(a=='['&&b==']'))
return true;
return false;
}
string ans="";
void dfs(int left,int right)
{
if(left>right)
return ;
if(left==right)
{
if(s[left]=='('||s[left]==')')
ans+="()";
else
ans+="[]";
return ;
}
if(rem[left][right]==right)
{
ans+=s[left];
dfs(left+1,right-1);
ans+=s[right];
return ;
}
dfs(left,rem[left][right]);
dfs(rem[left][right]+1,right);
}
int main()
{
if(gets(s)==NULL)
return 0;
ans="";
len=strlen(s);
for(int i=0; i<len; i++)
num[i][i]=1;
for(int i=1; i<len; i++)
{
for(int j=0; j+i<len; j++)
{
num[j][j+i]=10000;
if(OK(s[j],s[j+i]))
num[j][j+i]=(i==1)?0:num[j+1][j+i-1],rem[j][i+j]=i+j;
for(int k=0; k<i; k++)
{
if(num[j][j+k]+num[j+k+1][j+i]<num[j][j+i])
num[j][j+i]=num[j][j+k]+num[j+k+1][j+i],rem[j][j+i]=j+k;
}
}
}
dfs(0,len-1);
cout<<ans<<endl;
return 0;
}