POJ-1159-Palindrome(簡單dp)

題意:給你一個字符串,添加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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章