动态规划——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]构成对称的)。

状态转移方程:

动态规划——Poj 1159 Palindrome_第1张图片

从上面的分析可以看出,这个问题的实质是求最长公共子序列,只是这两个序列分别是串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)    提交结果


你可能感兴趣的:(动态规划,最长公共子序列)