链接:​​click here​

题意:

给你一串字符串,让你求最少加入几个字符,才能使得这个字符串是个回文串。

思路:

设a[i]是这个字符串,b[i]是这个字符串的逆序串。那么a[i],b[i]的最长公共子序列就是所求的字符串里拥有的最大的回文串。然后用总串长减去最大的回文串长度即为所求。求最长公共子序列的公式为:dp[i][j]=max(dp[i-1] [j],dp[i][j-1])if(a[i]==b[i])dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);

如果直接求的话,会超时。

用两种解决方法:

1,shor int数组

2,运用动态数组。

根据dp滚动的过程我们可以知道,dp[]i][j]的值不会与dp[i-2][0.....n]的值有关系。

那么可以把dp[i][j]的值覆盖到dp[i-2][j]上。即dp[i][j]为dp[i%2][j];

 代码:

<span style="font-size:12px;">#include <iostream>
#include <stdio.h>
#include <string.h>
#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=5005;
const int inf = 0x3f3f3f3f;
short int dp[maxn][maxn];
int a[maxn],b[maxn];
int n,m,i,j,length;
inline int input()
{
int res=0,f=1,c;
while(!isdigit(c = getchar()) && c!='-');
c=='-' ? f=0 : res=c-'0';
while(isdigit(c = getchar()))
res = res*10 + c-'0';
return f ? res : -res;
}
int main()
{
char str;
//n=input(); //POJ 竟然不支持快速输入,写成这样返回WA
scanf("%d",&n);
getchar();
for(i=1; i<=n; i++)
{
scanf("%c",&str);
a[i]=str;
b[n-i+1]=str;
}
for(i=0; i<=n; i++)
{
dp[i][0]=0;
dp[0][i]=0;
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
if(a[i]==b[j])
{
dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1); //关键
}
}
}
length=dp[n][n];
printf("%d\n",n-length); //总长减去回文子长即为所求
return 0;
}
</span>


滚动数组:

<span style="font-size:12px;">#include <iostream>
#include <stdio.h>
#include <string.h>
#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=5005;
const int inf = 0x3f3f3f3f;
short int dp[maxn][maxn];
int a[maxn],b[maxn];
int n,m,i,j,length;
inline int input()
{
int res=0,f=1,c;
while(!isdigit(c = getchar()) && c!='-');
c=='-' ? f=0 : res=c-'0';
while(isdigit(c = getchar()))
res = res*10 + c-'0';
return f ? res : -res;
}
int main()
{
char str;
//n=input();
scanf("%d",&n);
getchar();
for(i=1; i<=n; i++)
{
scanf("%c",&str);
a[i]=str;
b[n-i+1]=str;
}
dp[1][0]=dp[0][0]=0;
for(i=0; i<=n; i++)
{
//dp[i][0]=0;
dp[0][i]=0;
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
dp[i%2][j]=max(dp[i%2][j-1],dp[(i-1)%2][j]);
if(a[i]==b[j])
{
dp[i%2][j]=max(dp[i%23][j],dp[(i-1)%2][j-1]+1);
}
}
}
length=dp[n%2][n];
printf("%d\n",n-length);
return 0;
}
</span>