POJ-1159-Palindrome(简单dp)

来源:互联网 发布:mac air qq 远程桌面 编辑:程序博客网 时间:2024/06/14 17:44

题意:给你一个字符串,添加n个字符,使字符串变成回文字符串,求最小的n;
解题思路:设原字符串为strL,长度为len, 则strR为它的反向字符串。然后求出strL,strR两个字符串的最长公共子序列m.则最小的n为:len - m
还有应该注意的是如果dp数组是 len*len 话,内存会爆。所以要用滚动数组来写,dp数组大小开 2*n;
原因是:

for (int i = 1; i <= len; i++) {    for (int j = 1; j <= len; j++) {        if (strL[i] == strR[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", len - dp[len][len]);

可以看出求dp[i]时,只有dp[i - 1](这里我写了一维)所以我们只保存dp[i - 1]就行了。Ps:这里我感觉我想的不对,因为如果是这样的话那么完全可以开2*2,或者n*2的。但是这两种都无法求出结果。如果有读者知道的话欢迎留言,谢谢。、
ac代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 5005;char strL[N];char strR[N];int dp[2][N];int main(){    int n;    int len;    while (~scanf("%d", &n)) {        memset(dp, 0, sizeof(dp));        scanf("%s", strL + 1);        len = strlen(strL + 1);        for (int i = 1; i <= len; i++) {            strR[len - i + 1] = strL[i];        }    //  printf("%s  %s\n", strL + 1, strR + 1);        for (int i = 1; i <= len; i++) {            for (int j = 1; j <= len; j++) {                if (strL[i] == strR[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]);                }            }        }        printf("%d\n", len - dp[len % 2][len]);    }    return 0;} 
0 0
原创粉丝点击