状态转移
d(i,j)表示子串S[i~j]至少需要加几个括号
递推写法 快
#include <bits/stdc++.h> using namespace std; const int maxn = 100+5; char S[maxn]; int n,d[maxn][maxn]; bool match(char a, char b){ return (a=='(' && b==')') || (a=='[' && b==']'); } void dp(){ for(int i=0; i<n; i++){ d[i+1][i] = 0; d[i][i] = 1; } for(int i=n-2; i>=0; i--) for(int j=i+1; j<n; j++){ d[i][j] = n; if(match(S[i],S[j])) d[i][j] = min(d[i][j],d[i+1][j-1]); for(int k=i; k<j; k++){ d[i][j] = min(d[i][j],d[i][k]+d[k+1][j]); } } } void print(int i,int j){ if(i>j) return ; if(i==j){ if(S[i]=='(' || S[i]==')') printf("()"); else printf("[]"); return; } int ans = d[i][j]; if(match(S[i],S[j]) && ans==d[i+1][j-1]) { printf("%c",S[i]); print(i+1,j-1); printf("%c",S[j]); return ; } for(int k=i; k<j; k++){ if(ans == d[i][k]+d[k+1][j]){ print(i,k); print(k+1,j); return; } } } void readline(char* S){ fgets(S,maxn,stdin); } int main(){ int T; readline(S); sscanf(S,"%d",&T); readline(S); while(T--){ readline(S); n = strlen(S)-1; memset(d,-1,sizeof(d)); dp(); print(0,n-1); printf("\n"); if(T) printf("\n"); readline(S); } }
记忆化搜索 慢
#include <bits/stdc++.h> using namespace std; const int maxn = 100+5; char S[maxn]; int n,d[maxn][maxn]; bool match(char a, char b){ return (a=='(' && b==')') || (a=='[' && b==']'); } int dp(int i,int j){ if(i > j) return 0; if(i==j) return 1; if(d[i][j]>=0) return d[i][j]; d[i][j] = n; if(match(S[i],S[j])) d[i][j] = min(d[i][j],dp(i+1,j-1)); for(int k=i; k<j; k++) d[i][j] = min(d[i][j],dp(i,k)+dp(k+1,j)); return d[i][j]; } void print(int i,int j){ if(i > j) return; if(i==j){ if(S[i]=='(' || S[i]==')') printf("()"); else printf("[]"); return; } int ans = dp(i,j); if(match(S[i],S[j]) && ans==dp(i+1,j-1)){ printf("%c",S[i]); print(i+1,j-1); printf("%c",S[j]); return; } for(int k=i; k<j; k++) if(ans == dp(i,k)+dp(k+1,j)){ print(i,k); print(k+1,j); return; } } void readline(char* S) { fgets(S, maxn, stdin); } int main() { int T; readline(S); sscanf(S, "%d", &T); readline(S); while(T--) { readline(S); n = strlen(S) - 1; memset(d, -1, sizeof(d)); print(0, n-1); printf("\n"); if(T) printf("\n"); readline(S); } return 0; }