题意:求长度为n的字符串最少需要添加几个字符可以使之成为回文串。
思路:求原串和反串的最长公共子序列。然后总长减去最大的lcs的值即可。
用int 内存占用约95M, 题目要求是64M显然超内存, 所以用short
int 。 还能用滚动数组。
#include<iostream>
#include <cstdio>
#include <cstring>
#include<vector>
using namespace std;
const int MAXN=5005;
char s1[MAXN], s2[MAXN];
short int dp[MAXN][MAXN];
short int Max(short int a, short int b)
{
if(a>b)
return a;
return b;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
scanf("%s", s1+1);
memset(dp, 0, sizeof(dp));
int len = strlen(s1+1);
for(int i=1;i<=len;++i)
s2[i]=s1[len-i+1];
s2[len+1]='\0';
for(int i=1;i<=len;i++)
{
for(int j=1;j<=len;++j)
{
if(s1[i]==s2[j])
dp[i][j]=Max(dp[i-1][j-1]+1, dp[i][j]);
else
dp[i][j]=Max(dp[i][j-1], dp[i-1][j]);
}
}
printf("%d\n", len-dp[len][len]);
}
return 0;
}
滚动数组
每两行求一个lcs, 往下递推。
#include<iostream>
#include <cstdio>
#include <cstring>
#include<vector>
using namespace std;
const int MAXN=5005;
char s1[MAXN], s2[MAXN];
short int dp[2][MAXN];
short int Max(short int a, short int b)
{
if(a>b)
return a;
return b;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
scanf("%s", s1+1);
memset(dp, 0, sizeof(dp));
int len = strlen(s1+1);
for(int i=1;i<=len;++i)
s2[i]=s1[len-i+1];
unsigned short int MAX=0;
s2[len+1]='\0';
for(int i=1;i<=len;i++)
{
for(int j=1;j<=len;++j)
{
if(s1[i]==s2[j])
dp[i%2][j]=Max(dp[(i-1)%2][(j-1)]+1, dp[i%2][j]);
else
dp[i%2][j]=Max(dp[i%2][j-1], dp[(i-1)%2][j]);
//MAX=Max(dp[i%2][j],MAX);
}
}
printf("%d\n", len-dp[len%2][len]);
}
return 0;
}