动态规划---最长子串/子序列问题序列1

本文介绍了使用动态规划方法解决最长回文子串和最长上升子序列的问题。对于最长回文子串,通过状态定义dp[i][j]表示s[i, j]是否为回文子串,利用状态转移方程进行求解;最长上升子序列则通过动态规划一维数组dp[i]表示以nums[i]结尾的上升子序列长度,以及二分法解法提高效率。" 88840829,8432326,使用树链剖分与树状数组解决Codeforces 165D边染色问题,"['树形结构', '数据结构', '图论', '算法', '动态规划']
摘要由CSDN通过智能技术生成

动态规划---最长子串/子序列问题序列1

5. 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:
输入: "cbbd"
输出: "bb"

解法1:动态规划

  • 1、当子串只包含 1 个字符,它一定是回文子串;
  • 2、当子串包含 2 个以上字符的时候:如果 s[l, r] 是一个回文串,例如 “abccba”,那么这个回文串两边各往里面收缩一个字符(如果可以的话)的子串 s[l + 1, r - 1] 也一定是回文串,即:如果 dp[l][r] == true 成立,一定有 dp[l + 1][r - 1] = true 成立。
    根据这一点,我们可以知道,给出一个子串 s[l, r] ,如果 s[l] != s[r],那么这个子串就一定不是回文串。如果 s[l] == s[r] 成立,就接着判断 s[l + 1] 与 s[r - 1],这很像中心扩散法的逆方法。
  • 时间和空间都是o(n^2).
  • 强调:
    状态定义: dp[i][j] 表示数组子串 s[i, j] 是否为回文子串。
    状态转移方程: dp[l, r] = (s[l] == s[r] and (r - l <= 2 or dp[l + 1, r - 1]))
class Solution {
   
    public String longestPalindrome(String s) {
   
        if (s.length() <= 1) {
   
            return s;
        } 
        int len = s.length();
        int longestStrLength = 1;
        String longestStr = s.substring(0,1);
        //dp[left][right] 表示从left到right是否是回文子串
        boolean[][] dp = new boolean[len][len];
        for (int right=0; right<len; right++) {
   
            for (int left=0; left<right; left++) {
   
                //1 如果 dp[l, r] = true 那么 dp[l + 1, r - 1] 也一定为 true,所以反过来递推
                //2 剪枝:如果left到right间的数只有一个或者没有,比如left=1> right=2(中间没有数)或者1>3(中间只有一个数),则不用判断,中间的数肯定是回文的
                //3 left到right间的数:至少有2个才有判断:dp[left+1][right-1]的必要。
                if (s.charAt(left) == s.charAt(right) && (right-left <=2 || dp[left+1][right-1])) {
   
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值