poj-1159

22 篇文章 0 订阅
// 400K	610MS	G++ 
#include <stdio.h>
#include <string.h>

using namespace std;

#define MAX 5005

// short DP[MAX][MAX];
int DP[MAX];
int tmp[MAX];

char str[MAX];
int length;

// void solve() {
// 	memset(DP, 0xff, sizeof(DP));
// 	for (int i = length-1; i >= 0; i--) {
// 		for (int j = i; j <= length-1; j++) {
// 			if (i == j) { // only 1 char, no 
// 				DP[i][j] = 0;
// 			} else { // j > i
// 				if (str[i] == str[j]) { // both 1st and last char equal
// 					if (i+1 < j) { // if some char bertween i and j
// 						DP[i][j] = DP[i+1][j-1];
// 					} else { // if no chat between i and j
// 						DP[i][j] = 0;
// 					}
// 				} else {
// 					int res1 = 1 + DP[i+1][j];
// 					int res2 = 1 + DP[i][j-1];
// 					DP[i][j] = res1 < res2 ? res1: res2;
// 				}
// 			}
// 		}
// 	}
// 	printf("%d\n", DP[0][length-1]);
// }

void solve() {
	memset(DP, 0xff, sizeof(DP));
	memset(tmp, 0xff, sizeof(tmp));

	for (int i = length-1; i >= 0; i--) {
		memcpy(tmp, DP, sizeof(tmp));
		for (int j = i; j <= length-1; j++) {
			if (i == j) { // only 1 char, no insert
				DP[j] = 0;
			} else { // j > i
				if (str[i] == str[j]) { // both 1st and last char equal
					if (i+1 < j) { // if some char bertween i and j
						DP[j] = tmp[j-1];
					} else { // if no chat between i and j
						DP[j] = 0;
					}
				} else {
					int res1 = 1 + DP[j];
					int res2 = 1 + DP[j-1];
					DP[j] = res1 < res2 ? res1: res2;
				}
			}
		}
	}
	printf("%d\n", DP[length-1]);
}

int main() {
	while(scanf("%d", &length) != EOF) {
		scanf("%s", str);
		solve();
	}
}

基本经典DP题(从传统方法看),DP[i][j] 表示把输入的字符串S 从i 到j的部分变为回文串所需要的最少插入字符树

 
那么 DP[i][j]:

case 1: i ==j , 只有一个字符,本身就是回文,不同插入.

case 2: i > j: 没有意义的情况,直接默认-1即可。

case 3: i < j:

subcase 1: 如果 S[i] == S[j] , 那么如果i+1<j(中间还有字符串), 那么就 = DP[i+1][j-1], 否则 = 0

subcase 2: 如果 S[i] != S[j], 那么这时候两个选择: (1) 在j后面插入一个S[i], 那么 = DP[i+1][j] + 1

 (2) 在i前面差一个S[j], 那么  =DP[i][j-1] + 1,

两者找最小即可.

一开始用int开的二维数组,直接MLE,改成short过关,尝试了下滚动数组压成一维,发现在这种方法下,不能压缩,

结合上面分析,可以看到 DP[i][j] 依赖 于 DP[i+1][j-1], DP[i+1][j] 和 DP[i][j-1],这就出现了矛盾:

DP[i][j] 依赖于DP[i+1][j-1] 和DP[i][j-1],  如果是滚动一维数组的话,这就说明DP[j] 既依赖于更新前的DP[j-1] 也依赖于更新后的DP[j-1], 在只有一个数组的情况下,是不可能两者兼的, 其实解决应该也是简单的,既然依赖了两层,那么可以搞两个滚动的一维数组A B应该就可以解决这个问题,A和以前一样作用, 每轮i迭代时拷贝一份当前的A到B, 就可以了,B此时保存的就是上一轮的DP值,A可以放心更新.

看到discuss后面还有人说本题实质是求该字符串和自己反向字符串的最长字符串距离,也要好好想想. 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值