题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号“待字闺中”
原题给定字符串,可以通过插入字符,使其变为回文。求最少插入字符的数量。例如:
1. ab最少插入1个字符,变为*b*ab
2. aa最少插入0个字符
3. abcd最少插入3个字符,*dcb*abcd
分析:根据回文串的定义,很容易获得递归思路,首先比较第一个和最后一个字符,相等则插入个数等于中间的插入个数,不等,则可以通过在开头或最后添加一个字符,使得两头相等,比如abcd可以转化为abcda或dabcd,这样,递归方程为:当str[i]==str[j]时,fun(i,j)=fun(i+1,j-1);否则fun(i,j)=min(fun(i+1,j),fun(i,j-1))+1.容易看出,该递归具有重复子序列,加上题目要求最短,故有最优的含义,故可转化为动态规划,动态规划的转移方程一般和递归方程一样,只是求解时需要利用先前的结果。本题中,可以看出求解方向是从两头向内部,和回文串的判断一样,动态规划的思路是先求len=1,然后len=2,然后……,故可得如下代码:
int minInsertChar(char* src) { if(src == NULL)return -1; int length = strlen(src); int i,len; int** dp = new int*[length+1]; for(i=0;i<=length;i++) { dp[i] = new int[length+1]; memset(dp[i],0,sizeof(int)*(length+1)); } for(len=1;len<length;len++)//长度从1到length-1 { for(i=length-len;i>=1;i--)//从后向前 { int j = i + len; if(src[i-1] == src[j-1])dp[i][j] = dp[i+1][j-1]; else dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1; } } int res = dp[1][length]; for(i=0;i<=length;i++)delete[] dp[i]; delete[] dp; return res; }
本代码只代表个人观点,如有错误,请指正,谢谢
原文地址:http://blog.csdn.net/fangjian1204/article/details/37656157