题目描述:
回文串定义:正向和反向的串是一样的。给出一个串,求问需要最少插入多少个字符才能变成一个回文串。
解题思路:
要找回文串需要插入的字符个数,就是选择某个空隙或者位置对折后看最大匹配的字符个数,不匹配的部分就是要插入的字符数了。
那么也就是说可以转换为求:倒过来和正过来比,找下最长相似串的长度,用总长度减去匹配的就是要插入的。比如说一个字符数为9的串,正着和倒着找到5个次序上相同的串。那么就是剩下的4个字符需要被补全。所以要插入的就是4.
那么现在的问题就是:如何找到两个字符串的,按照次序能匹配的最长的串呢?
令dp[i]=j表示匹配了i个字符时,最靠前的相对原字符串的索引下标j。【记录最靠前是为了让后面可匹配的长度更长一些】。通过遍历invert串来更新匹配dp[]。然后更新dp[i]->dp[1]。注意更新dp数组的内层循环,检查是否能被更新是判断是不是比原先的dp[]记录的索引靠前即可,如果遍历整个数组就会超时。
—— 诶呀,据队友说是典型的最长公共子串的问题。。。。好吧,回头看下。。。
代码:
#include
#include
#define N 5001
char input[N], invert_input[N];
int dp[N], dp_index=0, len;//dp[i]=j 表示匹配i个字符的最小索引位置。dp[0]=0;
main(){
int i, j, k;
scanf("%d",&len);
scanf("%s",input);
for(i=len-1;i>=0;i--){
invert_input[len-i-1] = input[i];
dp[i] = len;
}
dp[len] = len;// 1->len !!!!!
dp[0] = -1;
for(i=0;i
for(j=dp_index+1;j>0;j--){ // update dp[j]->dp[1]
for(k=dp[j-1]+1;k
if( input[k] == invert_input[i] ){
dp[j] = k;
//printf("update dp[%d] = %d\n",j,dp[j]);
break;
}
}
}
if(dp[dp_index+1]!=len){
dp_index++;
}
}
printf("%d\n", len - dp_index);
system("pause");
return 0;
}