一、分析
题目意思:给你个字符串。求最少须要加入几个字符使它变成一个回文字符串。
本来想着硬来,后来发现太麻烦了,然后才知道,这个题可以看作是最长公共子序列的动态规划题(—!),将字符串和字符串的逆向的最长公共子序列求出来,最后再用总长度减去即可。
而最长公共子序列最近正好有了解:
我们观察两个字符串,如果他们最后一个字符相同,则他们的LCS(最长公共子序列简写)就是两个字符串都去掉最后一个字符的LCS再加一。因为最后一个字符相同,所以最后一个字符是他们的子序列,把他去掉,子序列就少了一个,所以他们的LCS是他们去掉最后一个字符的字符串的LCS再加一。如果他们最后一个字符不相同,那他们的LCS就是X去掉最后一个字符与Y的LCS,或者是X与Y去掉最后一个字符的LCS,是他们两个中较长的那一个。写成数学公式就是:
所以根据这个就可以很容做出这题了。
二、代码
代码如下(示例):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 5001
int n;
int i,j;
char s[MAX];
short dp[MAX+1][MAX+1];
int max1(int a,int b)
{
return a>b?a:b;
}
int main()
{
while(scanf("%d",&n)==1)
{
getchar();
for(i=0;i<n;i++)
{
scanf("%c",&s[i]);
}
for (i=0;i<n;i++)//第一行,第一列都为0
{
dp[0][i]=0;
dp[i][0]=0;
}
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
{
if (s[i]==s[n-1-j])
dp[(i+1)][j+1]=dp[i][j]+1;
else
dp[(i+1)][j+1]=max1(dp[i][j+1],dp[(i+1)][j]);
}
}
printf("%d\n",n-dp[n][n]);
}
return 0;
}