最长回文子序列

题目:

8498:最长回文子序列 (tzcoder.cn)

描述

给定一个字符串s,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

输入

输入一个字符串s,长度不超过1000,全部由小写字母组成。

输出

最长回文子序列的长度。

样例输入

bbbab

样例输出

4

一道动态规划题,可以使用二维数组dp[i][j] 表示(注:这里i,j只是范围的表示字符,与接下来代码的i,j表示含义不同,以下的dp解释都是这样),i 表示区间左端 ,j 表示 区间右端 , 则dp[i][j]表示为字符串[i,j]范围中最长回文子序列。

那么这样的做法 初始化 怎么做呢?——dp[i][i]设为1(i属于字符串的总长度),单独的一个字符必然是回文串,且长度为1。

查找最长回文串的过程可以看成一个子串不断扩张的过程(可能向左,可能向右,也可能向两端)

状态转移方程:dp[i][j] 是表示[i,j]范围的回文串最值,可以遍历区间的左右端点 判断两端的字符是否相等 。

若相等 则说明回文串的长度肯定向左右各扩张了1单位,则dp[i,j]=dp[i+1,j-1]+2;

若不等 则说明回文串没有向两端扩张,那可能向左,也可能向右。但你不清楚是向哪边,那就取最值   dp[i][j] = max(dp[i+1][j], dp[i][j-1]);

代码(注释)

#include<bits/stdc++.h>
using namespace std;

const int N=1010;
string x;
int dp[N][N];

int main() 
{
    
    cin>>x;
    int len = x.size();
    for(int i=0;i<len;i++) dp[i][i]=1;//单个字符是 长度为 1 的回文串 

    for(int i=1;i<len;i++) //这里的 i是区间的长度 从2开始 
	{
        for(int j=0;j+i<len;j++) 
		{
            
            if(x[j] == x[j+i]) // j表示左端点    j+i代表右端点    [j,j+i]表示区间 
			{
                dp[j][j+i] = dp[j+1][j+i-1] + 2; // 说明回文序列向两端扩张了 
            } 
			else 
			{
                dp[j][j+i] = max(dp[j+1][j+i], dp[j][j+i-1]); //从[j+1,k],[j,k-1] 选择 最大的 回文序列 
            }
        }
    }
    cout << dp[0][len-1] << endl; //输出[0,len-1] 中 最大的回文序列 
    return 0;
}

代码(纯享版)

#include<bits/stdc++.h>
using namespace std;

const int N=1010;
string x;
int dp[N][N];

int main() 
{
    
    cin>>x;
    int len = x.size();
    for(int i=0;i<len;i++) dp[i][i]=1;

    for(int i=1;i<len;i++)
	{
        for(int j=0;j+i<len;j++) 
		{
            
            if(x[j] == x[j+i]) 
			{
                dp[j][j+i] = dp[j+1][j+i-1] + 2;
            } 
			else 
			{
                dp[j][j+i] = max(dp[j+1][j+i], dp[j][j+i-1]); 
            }
        }
    }
    cout << dp[0][len-1] << endl;
    return 0;
}

点个赞ba~    QWQ

THE  END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值