POJ 1159 Palindrome

问要将给定字符串变为回文字符串,最少插入多少个字符。
难点在于想清楚“如何转变为回文字符串”,若为回文字符串,则正序逆序完全相同,也就是lcs长度等于字符串长度。
所以如果要求插入字符的数量,就是正序逆序串lcs的长度减去字符串的长度。

还有一个问题是,如果直接这么写空间是不够的。要用到滚动数组。
因为dp是上下状态之间的转移,所以只需要有两个位置,一个保存上一状态,一个用于通过上一状态计算出当前的状态(也就是只需要用2个位置即可,开一个二维数组,用e来标志当前与上一状态,e=1-e实现状态之间的转换即可)。这个优化方法很好,学到惹。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
/*3 <= N <= 5000*/
#define MAX_N 5000

string origin, revo;
int dp[2][MAX_N+1];

int main()
{
    int length = 0, lcs = 0, ans = 0;
    cin >> length >> origin;

    /*
    //特判所有字符均相同
    char contain = origin[0];
    for(int i = 1;i < length;i++)
        if(origin[i]!=contain)
        {
            flag = 1;
            break;
        }

    if(!flag)
        ans = 0;
    //dp[i] 表示第i长度min insert

    else{

    dp[1] = dp[0] = 0;
    for(int i = 1;i < length;i++)
    {
        //找全部字符的奇偶
            int cnt = 0;
            for(int k = 0;k < length;k++)
                if(origin[i] == origin[k])
                    cnt++;
            if((cnt-1) != 0 && (cnt-1)%2 == 0)
                dp[i] = dp[i-1];
            else
                dp[i] = dp[i-1]+1;
    }
    //all in-odd / only 1 odd
    ans = dp[length-1];
    }

    printf("%d", ans);*/

    //correct ans
    revo = origin;
    reverse(revo.begin(), revo.end());


    int e = 0;
    //get revo origin lcs
    for(int i = 1;i <= length;i++)
    {
        //cout << "loop" << endl;
        e = 1-e;//1
        for(int j = 1;j <= length;j++)
        {
            //cout << "inner" << endl;
            if(revo[i-1] == origin[j-1])//position difference
                dp[e][j] = dp[1-e][j-1] + 1;
            else
                dp[e][j] = max(dp[1-e][j], dp[e][j-1]);
        }
    }
    lcs = dp[e][length];

    ans = length - lcs;

    printf("%d\n", ans);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值