问题描述:
已知:给定一字符串,只包含'a'-'z','A'-'Z'以及'0'-'9',插入任意个上述字符可使新字符串成为回文
求:使新字符串成为回文所需插入的最少字符数
输入:第1行,字符串长度n;第2行,字符串
输出:插入的最少字符数
Sample Input:
5
Ab3bd
Sample Output:
2
思路:
设字符串(ci, ..., cj)为一插入最少字符数获得的回文字符串,则(ci+1, ..., cj-1)也必为插入最少字符数获得的回文字符串,满足最优子结构
现设e(i, j)表示子串(ci, ..., cj)要变成回文需插入的最少字符数,则有如下递归表达式
原问题的最优解即为e(1, n)
代码:
#include <stdio.h>
#include <stdlib.h>
int n;
char * str;
short ** e; //为了节约空间占用,选择了short而不是int
void dp(){
e = (short **)malloc((n+1)*sizeof(short *));
for(int i = 0; i <= n; i++)
e[i] = (short *)malloc((n+1)*sizeof(short));
for(int i = 0; i < n; i++){
e[i][i] = 0;
e[i+1][i] = 0;
}
for(int l = 2; l <= n; l++){
for(int i = 0; i < n-l+1; i++){
int j = i+l-1;
e[i][j] = 1+((e[i+1][j] < e[i][j-1]) ? e[i+1][j] : e[i][j-1]);
if(str[i] == str[j])
e[i][j] = (e[i+1][j-1] < e[i][j]) ? e[i+1][j-1] : e[i][j];
else
e[i][j] = ((e[i+1][j-1]+2) < e[i][j]) ? (e[i+1][j-1]+2) : e[i][j];
}
}
printf("%d\n", e[0][n-1]);
}
int main(){
scanf("%d", &n);
str = (char *)malloc((n+1)*sizeof(char));
scanf("%s", str);
dp();
return 0;
}