POJ1159 Palindrome(dp加最少字母构成回文字符串)

来源:互联网 发布:淘宝好评后可以退款吗 编辑:程序博客网 时间:2024/05/21 17:33
Palindrome
Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 57426 Accepted: 19910

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

5Ab3bd

Sample Output

2

Source

IOI 2000


原题链接:http://poj.org/problem?id=1159

有这么个结论,需要加的字符的个数=原来字符串的长度-原来字符串和逆字符串的最长公共子序列的长度;
然后用滚动数组即可。

求最长公共序列的长度:
              

如左上图,先将该字符串到续,然后在和原来的字符串比较,如果两个字母相同,则将左上角的数字+1,否则该点的值等于该位置的的左边和上边数值的最大值,依次进行,最后右下角的数字极为最长公共子序列。该问题即可解决,但是该题的数据有点大(5000),如果用此方法会超内存!
所以可用滚动数字的方法解决。即:将此数组改成2*5000的即可!
此处有更详细的说明:http://blog.csdn.net/v_july_v/article/details/6695482

附上别人AC代码:
#include<stdio.h>#include<string.h>char str[5010];char s2[5010];int dp[2][5010];int main(){    int n,i,j;    while(scanf("%d",&n)!=EOF)    {        scanf("%s",str);        for(i=n-1; i>=0; i--)        {            s2[n-i-1]=str[i];        }        s2[n]='\0';        memset(dp,0,sizeof(dp));        for(i=1; i<=n; i++)        {            for(j=1; j<=n; j++)            {                if(str[i-1]==s2[j-1])                {                    dp[i%2][j]=dp[(i-1)%2][j-1]+1;                }                else                {                    //dp[i%2][j]=max(dp[(i-1)%2][j],dp[i%2][j-1]);                    if(dp[(i-1)%2][j]>dp[i%2][j-1])                    {                        dp[i%2][j]=dp[(i-1)%2][j];                    }                    else                    {                        dp[i%2][j]=dp[i%2][j-1];                    }                }            }        }        int l=dp[n%2][n];        printf("%d\n",n-l);    }
<span style="white-space:pre"></span>return 0;}



1 0