[POJ1159]Palindrome

题目大意:给你一个字符串(区分大小写),要求你添加最少的字符使其变成回文串,问最少添加几个字符。

思路:此题的答案=原字符串长度-原字符串与前后颠倒后的字符串的最长公共子串长度(LCS)。

求LCS用DP。

此题字符串最长能达5000,数组需要开5000*5000*int,会“炸”(MLE)。解决办法:①用short;②用滚动数组。

下面是两者的对比(上面是方法①,下面是方法②): 

由此可见,方法②完胜方法①(尤其是内存,相差49028K!)。(不会滚动数组的使用方法①也是个选择)

C++ Code:

方法①:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char a[5005],b[5005];
int dp[2][5005];
int l;
int main(){
	while(scanf("%d",&l)!=EOF){
		memset(a,0,sizeof(a));
		a[0]='^';
		scanf("%s",a+1);
		strcpy(b,a);
		memset(dp,0,sizeof(dp));
		reverse(b+1,b+l+1);
		int Max=0;
		for(int i=1;i<=l;i++)
		for(int j=1;j<=l;j++){
			if(a[i]==b[j])dp[i%2][j]=dp[(i-1)%2][j-1]+1;
			else
			dp[i%2][j]=max(dp[i%2][j-1],dp[(i-1)%2][j]);
			if(Max<dp[i%2][j])Max=dp[i%2][j];
		}
		printf("%d\n",l-Max);
	}
	return 0;
} 

方法②:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char a[5005],b[5005];
short dp[5005][5005];
int l;
int main(){
	while(scanf("%d",&l)!=EOF){
		memset(a,0,sizeof(a));
		a[0]='^';
		scanf("%s",a+1);
		strcpy(b,a);
		memset(dp,0,sizeof(dp));
		reverse(b+1,b+l+1);
		for(int i=1;i<=l;i++)
		for(int j=1;j<=l;j++){
			if(a[i]==b[j])dp[i][j]=dp[i-1][j-1]+1;
			else
			dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
		}
		printf("%d\n",l-dp[l][l]);
	}
	return 0;
} 

 

posted @ 2017-06-09 19:01  Mrsrz  阅读(180)  评论(0编辑  收藏  举报