动态规划——Poj 1159 Palindrome

 

1)   题目

Palindrome

Time Limit: 3000MS

 

Memory Limit: 65536K

Total Submissions: 46005

 

Accepted: 15688

Description

A palindrome is a symmetrical string, that is, 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 number of characters to be inserted into the string in order to obtain a palindrome. 

As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome. 

Input

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

Output

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

Sample Input

5

Ab3bd

Sample Output

2


2)    题意

题目给出回文的定义:一串字符,从左往右读和从右往左读是完全一样的。比如aba,从左往右读和从右往左读都是aba。

给出一串字符,求使该字符串是回文需要添加的最少字符个数。


3)    数据范围

字符串的长度n,3<=n<=5000。


4)    算法

动态规划法。设字符串为S,长度为L,d[i][j]表示以第i个字符为首,第j个字符为尾的字符串构成回文最少需要添加的字符个数,i和j的初值分别为1、L。

如果S[i] == S[j],即字符串两端的字符相等,d[i][j] = d[i+1][j-1],

即d[i][j]等于去掉头尾后的字符串的d值。

如果S[i] != S[j],此时划分出两个子问题,求d[i][j-1]和d[i+1][j],它两中较小的值再加1即为d[i][j](加上的1个字符是用于和S[i]或者S[j]构成对称的)。

状态转移方程:


从上面的分析可以看出,这个问题的实质是求最长公共子序列,只是这两个序列分别是串S的前一部分和串S后一部分的逆序列。


5)    代码

 

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define MIN(a, b) ((a) < (b) ? (a) : (b))

#define MAXSIZE 5005

//开始没有考虑内存问题,使用了int型,超内存限制,也可使用滚动数组解决
unsigned short d[MAXSIZE][MAXSIZE];

int ToPalindrome(char *s, int n)
{
	int i, j, k;
	//只有一个字符时,不需要添加字符
	for (i = 0; i < n; i++)
	{
		d[i][i] = 0;
	}
	//串长度为2时
	for (i = 1; i < n; i++)
	{
		if (s[i-1] == s[i])
		{
			d[i-1][i] = 0;
		}
		else
		{
			d[i-1][i] = 1;
		}
	}

	//串长度递增
	for (k = 2; k < n; k++)
	{
		for (i = 0, j = k; j < n; i++, j++)
		{
			if (s[i] == s[j])
			{
				d[i][j] = d[i+1][j-1];
			}
			else
			{
				d[i][j] = MIN(d[i][j-1], d[i+1][j]) + 1;
			}
		}
	}
	return d[0][n-1];
}

int main(void)
{
	char str[MAXSIZE];

	int n;
	while (scanf("%d", &n) != EOF)
	{
		getchar();
		gets(str);
		printf("%d\n", ToPalindrome(str, n));
	}
	return 0;
}

 

 

6)    测试数据

5

Ab3bd

3

aaa

7

Aabcdba

7)    提交结果


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值