[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;
} 

 

转载于:https://www.cnblogs.com/Mrsrz/p/6973358.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值