POJ1159 Palindrome(动态规划问题)

题目:

Description

A palindrome is a symmetrical string, thatis, a string read identically from left to right as well as from right to left.You are to write a program which, given a string, determines the minimal numberof characters to be inserted into the string in order to obtain apalindrome. 
As an example, by inserting 2 characters, the string "Ab3bd" can betransformed into a palindrome ("dAb3bAd" or "Adb3bdA").However, inserting fewer than 2 characters does not produce a palindrome. 

Input  Your program is to read fromstandard input. The first line contains one integer: the length of the inputstring N, 3 <= N <= 5000. The second line contains one string with lengthN. The string is formed from uppercase letters from 'A' to 'Z', lowercaseletters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercaseletters are to be considered distinct.

Output Your program is to write to standard output. The first line contains oneinteger, which is the desired minimal number.

Sample Input 

5

Ab3bd

Sample Outout

2


大概题意: 给你一个字符串,可在任意地方添加字符,求出最少添加几个数可以使这个字符串成为回文字符串。

大概的思路: 

1. 利用动规。设字符串为S,长度为L,d[i][j]表示以i个字母为首,第j个字符为尾的字符串构成回文最少需要添加的字符个数。这里的思想主要是想通过不断地短的字符串优化长的字符串,通过将每个小的取优,来确定出长的字符串所需要添加的最小字符数。这里的动态规划,首先要进行初始化,将d[i][i]进行赋值,初始成0.再将j-i等于的d数组初始化。接下来就是对进行状态转移,给出转移方程:如果s[i]==s[j]则可以将d数组进行缩小。否则,d[i][j]=min(d[i+1][j],d[i][j-1])+1。

除了上述方法外,我还看到一个新的方法,觉得还不错。将这道题进行变形,就是求原串与其逆串的最长公共子序列,然后用串长减去最长公共子序列的长度就是要添加的最少的字符数。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
#define MAXNUM 5005
#define MIN(a,b) ((a)<(b)?(a):(b))
unsigned short d[MAXNUM][MAXNUM];
int DP(char *s,int n)
{
    for(int i=0;i<n;i++)
        d[i][i]=0;
        for(int i=1;i<n;i++){
                if(s[i-1]==s[i])
                d[i-1][i]=0;
                else d[i-1][i]=1;
    }
    for(int k=2;k<n;k++){
        for(int i=0,j=k;j<n;j++,i++){
            if(s[i]==s[j])
                d[i][j]=d[i+1][j-1];
            else d[i][j]=MIN(d[i+1][j],d[i][j-1])+1;
        }
    }
    return d[0][n-1];
}

int main()
{
    int n;
    char a[MAXNUM];
    while(scanf("%d",&n)!=EOF){
        getchar();
        gets(a);
        printf("%d\n",DP(a,n));
    }
    return 0;
}


注意这题中如果正常开数组会爆内存,将类型改为unsigned short,或者利用滚动数组。另一个需要注意的是由于scanf不会把换行符读入,而这道题输入了换行,所以需要加一个getchar()把换行符给读掉。这里的字符串是用gets()读入的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值