Brackets sequence
题意:
有一串只包含"(",")","[","]“的字符串,例如”([)",现在想要给它补全括号,让它变成正常的括号序列,比如[()],([()]),问最短的序列是什么
解法:
区间dp
用 d p [ i ] [ j ] dp[i][j] dp[i][j]来表示区间i~j内要补充的最短长度是多少
则有两种情况:
- s[i]和s[j]匹配,为括号对,则 d p [ i ] [ j ] dp[i][j] dp[i][j]= d p [ i + 1 ] [ j − 1 ] dp[i+1][j-1] dp[i+1][j−1]
- s[i]和s[j]不匹配, d p [ i ] [ j ] = m i n ( d p [ i ] [ k ] + d p [ k + 1 ] [ j ] ) ∀ k ∈ [ i , j ) dp[i][j]=min(dp[i][k]+dp[k+1][j])\forall k \in[i,j) dp[i][j]=min(dp[i][k]+dp[k+1][j])∀k∈[i,j)
提前预处理好所有的 d p [ i + 1 ] [ i ] dp[i+1][i] dp[i+1][i],因为j=i+1且i与j配对时
d p [ i ] [ i + 1 ] = m i n ( d p [ i ] [ i + 1 ] , d p [ i + 1 ] [ i ] ) dp[i][i+1]=min(dp[i][i+1],dp[i+1][i]) dp[i][i+1]=min(dp[i][i+1],dp[i+1][i]),此时应该是0,区间内所有括号配对
d p [ i ] [ i ] = 0 dp[i][i]=0 dp[i][i]=0,所有括号再加一个即可完成配对
代码:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int maxm=1e2+10;
string s;
int dp[maxm][maxm];
bool input(){
getline(cin,s);
getline(cin,s);
return !s.empty();
}
bool match(char a,char b){
return (a=='('&&b==')')||(a=='['&&b==']');
}
void print(int i,int j){
if(i>j) return ;
else if(i==j){//单个字符配括号
printf((s[i]=='('||s[i]==')')?"()":"[]");
return ;
}else if(match(s[i],s[j])&&dp[i][j]==dp[i+1][j-1]){//匹配
printf("%c",s[i]);
print(i+1,j-1);
printf("%c",s[j]);
return ;
}else{//不匹配则找最优分割点
for(int k=i;k<j;k++){
if(dp[i][j]==dp[i][k]+dp[k+1][j]){
print(i,k);
print(k+1,j);
return ;
}
}
}
}
int main(){
int T;
scanf("%d",&T);
getchar();
while(T--){
if(!input()){
puts("\n");
continue;
}
memset(dp,0x3f,sizeof(dp));
int len=s.size();
for(int i=0;i<len;i++){
dp[i+1][i]=0;
dp[i][i]=1;
}
for(int i=len-2;i>=0;i--){
for(int j=i+1;j<len;j++){
dp[i][j]=len;
if(match(s[i],s[j])){
dp[i][j]=min(dp[i][j],dp[i+1][j-1]);
}
for(int k=i;k<j;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
}
}
print(0,len-1);
printf("\n");
if(T) printf("\n");
}
}
注意要点:
Ⅰ:
代码本身很好理解,但是输入输出有坑,可能会有空行,详见代码中input()
Ⅱ:
注意区间dp的预处理,即解法中的 d p [ i + 1 ] [ i ] dp[i+1][i] dp[i+1][i]和 d p [ i ] [ i ] dp[i][i] dp[i][i]的细节处理
Ⅲ:
注意递归输出部分,即代码中print()