《算法艺术与信息学竞赛》 P113~P115,注释掉的内容可以求得最少匹配完全数量。
path 表示的是在某个中间序列得到了较小的路径序号。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX_N 105
#define MAX 1<<20
#define min(a,b) (a)<(b)?(a):(b)
char str[MAX_N];
int dp[MAX_N][MAX_N],len,path[MAX_N][MAX_N];
void init(){
len=strlen(str+1);
memset(dp,0,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=0;i<=len;i++)
dp[i][i]=1;
}
void MinMatch(){
for(int p=1;p<=len-1;p++){
for(int i=1;i<=len-p;i++){
int j=i+p;
dp[i][j]=1<<20;
for(int q=i;q<=j;q++)
if((str[i]=='('&& str[j]==')')
|| (str[i] =='[' && str[j] == ']') ){
if(dp[i][j]>dp[i+1][j-1])
dp[i][j]=dp[i+1][j-1];
// dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
}
/* if(str[i] =='(' || str[i] == '['){
dp[i][j]=min(dp[i][j],dp[i+1][j])+1;
}
if(str[j] == ')' || str[j] == ']'){
dp[i][j]=min(dp[i][j],dp[i][j-1])+1;
}
*/
for(int k=i;k<j;k++){
//dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]);
if(dp[i][j]>dp[i][k]+dp[k+1][j])
dp[i][j]=dp[i][k]+dp[k+1][j],path[i][j]=k;
}
}
}
}
void Output(int i,int j){
if(i>j) return ;
if(i==j){
if(str[i]=='(' || str[i] ==')')
cout<<"()";
else
cout<<"[]";
}
else if(!path[i][j]){
cout<<str[i];
Output(i+1,j-1);
cout<<str[j];
}
else
Output(i,path[i][j]),Output(path[i][j]+1,j);
}
int main(){
while(gets(str+1)){
init();
if(len==0){
cout<<endl;
continue;
}
MinMatch();
Output(1,len);
cout<<endl;
}
return 0;
}