题目大意:给一个字符串,要求添加最少个字符,把它变成回文串,并输出。
思路:
区间dp,dp[i][j] 表示区间(i, j) 内的字符串添加的最少个数,
变成回文串那么,
如果str[i]==str[j], dp[i][j] = dp[i+1][j-1] + 1
否则dp[i][j] = min{dp[i+1][j], dp[i][j-1]} + 1;
题目要输出方案,那么只要再开一个数组,根据状态转移递归输出即可
思路:
区间dp,dp[i][j] 表示区间(i, j) 内的字符串添加的最少个数,
变成回文串那么,
如果str[i]==str[j], dp[i][j] = dp[i+1][j-1] + 1
否则dp[i][j] = min{dp[i+1][j], dp[i][j-1]} + 1;
题目要输出方案,那么只要再开一个数组,根据状态转移递归输出即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1005;
char str[N];
int dp[N][N];
void print_path(int l,int r) {
if(l > r) {
return ;
}
if(l == r) {
putchar(str[l]);
}else if(str[l] == str[r]) {
putchar(str[l]);
print_path(l+1,r-1);
putchar(str[r]);
}else if(dp[l+1][r] > dp[l][r-1]){
putchar(str[r]);
print_path(l,r-1);
putchar(str[r]);
}else {
putchar(str[l]);
print_path(l+1,r);
putchar(str[l]);
}
}
int main() {
int cas = 0;
while(scanf("%s",str) != EOF) {
int len = strlen(str);
memset(dp,0,sizeof(dp));
for(int i = 0; i <= len; i++) {
dp[i][i] = 1;
}
for(int l = len-1; l >= 0; l--) {
for(int r = l; r < len; r++) {
if(str[l] == str[r]) {
dp[l][r] = dp[l+1][r-1];
}else if(dp[l+1][r] > dp[l][r-1]){
dp[l][r] = dp[l][r-1]+1;
}else {
dp[l][r] = dp[l+1][r]+1;
}
}
}
printf("%d ",dp[0][len-1]);
print_path(0,len-1);
printf("\n");
}
return 0;
}