给定字符串,可以通过插入字符,使其变成回文,求最少插入字符的数量。
比如
poj 1159 这题
Ab5db可以最少插入两个字符 构成回文 Abd5dbA
abcd可以最少插入三个字符 构成回文 abcdcba
分析:
用动态规划。
设字符为str[] ,长度为n,下标的开始为l,结束为h
那么如果str[l]==str[h] ,则只需要看str从l+1到h-1的回文如何构成
如果str[l]!=str[h],那么要插入的字符要么跟str[l]相同,要么跟str[h]相同,假设:
跟str[l]相同,则只需判断l+1到h的字符如何构成回文
跟str[h]相同,则只需判断l到h-1的字符如何构成回文
由于是最少插入字符数,那么取上述两种情况中值最小的一种即可
递推公式为
f[l][h]=(str[l]==str[h])?f[l+1][h-1]:(min(f[l+1][h],f[l][h-1])+1)
下面是我的源代码,仅供参考:
#include<iostream>
using namespace std;
#define MAX 5005
char str[MAX];
short int fmi[MAX][MAX];
inline int min(int a,int b)
{
return a<b?a:b;
}
short int fmiDP(int N)
{
int i,j,gap;
for(i=0;i<MAX;i++)
for(j=0;j<MAX;j++)
fmi[i][j]=0;
for(gap=1;gap<N;gap++) //core code
for(i=0,j=gap;j<N;i++,j++)
fmi[i][j]=((str[i]==str[j])?fmi[i+1][j-1]:(min(fmi[i+1][j],fmi[i][j-1])+1));
return fmi[0][N-1];
}
int main()
{
int N;
while(cin>>N && N)
{
cin>>str;
cout<<fmiDP(N)<<endl;
}
return 0;
}