思路:动态规划,dp[i][j]表示i到j之间最少需要添加的字符的个数,path[i][j]记录i到j之间添加字符个数为dp[i][j]时的分割位置,path[i][j]初始化为-1,就表示i到j之间没有分割位置。
状态转移方程:dp[i][j] = min(dp[i][j],dp[i][k-1]+dp[k+1][j-1]),其中str[k]必须要与str[j]匹配,k即为分割位置。
打印字符的时候用dfs。
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 111; char s[MAXN]; int dp[MAXN][MAXN]; int path[MAXN][MAXN]; bool canMacth(char c1, char c2){ return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']'); } void dfs(int n, int m){ if(n > m) return; if(path[n][m] == -1){ if(n == m){ if(s[n] == '(' || s[n] == ')') printf("()"); else printf("[]"); }else{ if(canMacth(s[n], s[m])){ printf("%c", s[n]); dfs(n+1, m-1); printf("%c", s[m]); }else{ if(s[m] == ')' || s[m] == ']'){ dfs(n, m-1); printf("%c%c", s[m] == ')'?'(':'[', s[m]); }else{ dfs(n, m-1); printf("%c%c", s[m], s[m] == '('?')':']'); } } } } else{ dfs(n, path[n][m]-1); printf("%c", s[path[n][m]]); dfs(path[n][m]+1, m-1); printf("%c", s[m]); } } int main(){ while(gets(s) != NULL){ int len = strlen(s); memset(path, -1, sizeof(path)); for(int i = 0;i < MAXN;i ++) dp[i][i] = 1; for(int i = 1;i < len;i ++){ for(int j = i-1;j >= 0;j --){ path[j][i] = -1; dp[j][i] = dp[j][i-1]+1; for(int k = j;k < i;k ++){ if(canMacth(s[k], s[i])){ if(dp[j][i] > dp[j][k-1] + dp[k+1][i-1]){ dp[j][i] = dp[j][k-1] + dp[k+1][i-1]; path[j][i] = k; } } } } } dfs(0, len-1); printf(" "); } return 0; }