[LeetCode]05. Longest Palindromic Substring (动态规划)

问题

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

Output: "bb"

思路

  • 简单描述:对于长度为n的字符串s,找出以第i个字符起始的长度为len的最长回文。(以下用s[i]表示字符串s的第i个字符,0为起点)
  • 问题分割:要想知道长度为len的子串是否是回文,就要知道长度为len-2的子串是否为回文。
  • 子问题
    1. 单个字符自己是回文。
    2. 相邻两个字符相等,这个长度为2的子串是回文。
  • 初始化:用矩阵dp[i][j]表示子串s[i]s[j]是否是回文。是回文,dp[i][j]=true,反之为false。对于子问题1,给所有dp[i][i] (i∈[0,n-1])赋值为true。对于子问题2,给所有满足s[i]=s[i+1]dp[i][i+1](i∈[0,n-2])赋值为true

代码

public class LongestPalindromicSubstring {
    public String longestPalindrome(String s) {
        boolean[][] dp = new boolean[s.length()][s.length()];
        int left = 0;
        int maxLen = 1;

        // 初始化1.每个单字设置为true
        for (int i = 0; i < s.length(); i++) {
            dp[i][i] = true;
        }

        // 初始化2. 相邻的字符相等也是回文,设置为true
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.charAt(i) == s.charAt(i + 1)) {
                dp[i][i + 1] = true;
                left = i;
                maxLen = 2;
            }
        }

        // 递推 寻找长度为3和3以上的回文子串
        for (int len = 3; len <= s.length(); len++) { // 当前子串长度为len
            for (int i = 0; i < s.length() - len + 1; i++) { // 当前子串起始位置i
                int j = i + len - 1; // 子串尾端位置j. j-i=len-1
                if (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]) {
                    // if条件句解释: 1. 当前子串长度为3时, i+1=j-i=中间的字符
                    // 2. 当前子串长度为4时, i+1+1=j-i 即初始化2中检查相邻字符是否一样
                    // 也就是说,以每个字符为起始的每个长度的子串都做了判断,并将结果存储在了dp[][]中
                    // 下一轮长度+1时,可利用上一轮的判断结果
                    // 每一个字符,都遍历了长度1~n的子串,所以时间复杂度O(n^2)
                    dp[i][j] = true;
                    left = i;
                    maxLen = len;
                }
            }
        }
        return s.substring(left, left + maxLen);
    }
}

参考

Longest Palindromic Substring

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值