题目:
回文是一个对称的字符串,换句话说,这个字符串从左到右读和
从右到左读是一样的。给出一个字符串,你要编一个程序,决定
要插入的最少的字符个数,使得原字符串成为一个回文。
比如,字符串”Ab3bd”中插入2个字符,使得它能变成一个
回文("dAb3bAd" 或 "Adb3bdA")。如果插入少于2个字符,将无法产生回文。
求最少插入几个字符,使其变成回文字符串
分析:
S1 = Ab3bd 的反转为
S2 = db3ba
要使S1变成回文字符串,可先求出S1,S2的最长公共子序列,用n-lcs(S1,S2)即可,
本题转化为求S1,S2的最长公共子序列
状态转移方程:
if(s1[i]==s2[j])
dp[i][j] = dp[i-1][j-1]+1
else
dp[i][j] = max{dp[i-1][j],dp[i][j-1]}
答案为dp[n][n]
#include <iostream>
#include <cstring>
using namespace std;
#define X 5002
short dp[X][X]; //注意到内存限制
char s[X];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>s[i];
s[n+1] = '\0';
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++) //求反串与正串的LCS数
{
for(int j=n;j;j--) //从后面搜起,即为该反串
{
if(s[i]==s[j])
dp[i][j] = dp[i-1][j+1]+1;
else
dp[i][j] = Max(dp[i-1][j],dp[i][j+1]);
}
}
cout<<n-dp[n][1]<<endl;
}
return 0;
}