用dp[i][j]记录下从i到j所缺少的括号数量,那么dp[i][i] = 1,dp[i][j] = dp[i][k] + dp[k+1][j],另外如果第i个字符和第j个字符匹配,则dp[i][j]应先被置为dp[i+1][j-1]。
由于要输出最终的字符串,所以使用pos[i][j]记录下缺省的位置,输出也是一个难点,要写一个函数递归的输出配对后的合法字符串,代码仅供参考。
//POJ1141
#include <cstdio>
#include <cstring>
const int maxn = 100 + 10;
char bracket[maxn];
//dp[i][j] = dp[i+1][j-1]
//dp[i][j] = dp[i][k] + dp[k+1][j]
int dp[maxn][maxn];
int pos[maxn][maxn];
bool match(int s, int t) {
if ((bracket[s] == '(' && bracket[t] == ')') ||
(bracket[s] == '[' && bracket[t] == ']')) {
return true;
}
return false;
}
void print_ans(int s, int t) {
if (s > t) {
return;
}
if (s == t) {
if (bracket[s] == '(' || bracket[t] == ')') {
printf("()");
} else {
printf("[]");
}
} else if (pos[s][t] == -1) {
printf("%c", bracket[s]);
print_ans(s+1, t-1);
printf("%c", bracket[t]);
} else {
print_ans(s, pos[s][t]);
print_ans(pos[s][t] + 1, t);
}
}
int main(int argc, char const *argv[]) {
gets(bracket);
int n = strlen(bracket);
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
}
memset(pos, -1, sizeof(pos));
for (int i = 1; i < n; i++) {
for (int j = 0; j + i < n; j++) {
int s = j, t = j + i;
dp[s][t] = 0x3ff;
if (match(s, t)) {
dp[s][t] = dp[s+1][t-1];
}
for (int k = s; k < t; k++) {
if (dp[s][t] > dp[s][k] + dp[k+1][t]) {
dp[s][t] = dp[s][k] + dp[k+1][t];
pos[s][t] = k;
}
}
}
}
print_ans(0, n - 1);
putchar('\n');
return 0;
}