码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4745 最长回文子序列

时间:2015-05-03 14:42:07      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:dp

对任意字符串,如果头和尾相同,那么它的最长回文子序列一定是去头去尾之后的部分的最长回文子序列加上头和尾。如果头和尾不同,那么它的最长回文子序列是去头的部分的最长回文子序列和去尾的部分的最长回文子序列的较长的那一个。
设字符串为s,f(i,j)表示s[i..j]的最长回文子序列。
状态转移方程如下:
当i>j时,f(i,j)=0。
当i=j时,f(i,j)=1。
当i<j并且s[i]=s[j]时,f(i,j)=f(i+1,j-1)+2。
当i<j并且s[i]≠s[j]时,f(i,j)=max( f(i,j-1), f(i+1,j) )。
注意如果i+1=j并且s[i]=s[j]时,f(i,j)=f(i+1,j-1)+2=f(j,j-1)+2=2,这就是“当i>j时f(i,j)=0”的好处。
由于f(i,j)依赖i+1,所以循环计算的时候,第一维必须倒过来计算,从s.length()-1到0。
最后,s的最长回文子序列长度为f(0, s.length()-1)。


对这道题,因为是环  所以得处理下。

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

int dp[2010][2010];
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int n,i,j;
    int num[2100];
    while(~scanf("%d",&n),n)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
            num[i+n]=num[i];
        }
        memset(dp,0,sizeof(dp));
        int Max=0;
        for(i=n;i>=1;i--)
        {
            dp[i][i]=1;
            for(j=i+1;j<=n;j++)
            {
                if(num[i]==num[j]) dp[i][j]=dp[i+1][j-1]+2;
                else dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
            }
        }
        for(i=1;i<=n;i++)
        if(dp[1][i]+dp[i+1][n]>Max) Max=dp[1][i]+dp[i+1][n];
        printf("%d\n",Max);
    }    
    return 0;
}

hdu 4745 最长回文子序列

标签:dp

原文地址:http://blog.csdn.net/zxf654073270/article/details/45458597

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!