Leetcode 05 最长回文子串

69 阅读2分钟

该题目考虑使用动态规划来解决,对于动态规划来说,我们通常需要一个状态容器,然后对状态容器进行初始化,之后我们需要找到动态规划的转移方程,状态方程如下所示:

45b6f69c252b4c25aa910990d82d395.jpg

代码执行流程
1. 判断当前字符串的长度,如果字符串的长度为1那么一定是回文串,如果是空串那么没有回文串,返回空,此时返回输入字符串即可;
2. 创建动态规划的初始容器,用于判断dp[i][j]是否是回文串
3. 对状态容器进行初始化
4. 存储两个int型变量,一个用于存储回文串的长度,另一个用于存储起始坐标,因为单串一定是回文串,因此max的初始值为1
5. 开始循环,j遍历整个字符串,i的值需要比j小,因为dp矩阵中存放的是dp[i][j]是否是回文串,i>j不存在物理意义
    -首先进行判断,如果i和j位置所在的字符不同直接返回false,因为首尾不同
    -如果相同的话就进行判断,当j-i<=2的时候返回true,因为进入该判断时说明i和j的位置字符一定相同,有三种无需继续往下判断的状态,分别是ABA,AA,A,分别对应j-i=2,1,0;
    -如果上述判断为false,那么结果就是i+1,j-1,也就是CBABC,C=C判断完了,需要判断BAB是否是子串
    -判断结束后,如果max的长度变长了,我们修改起始指针,以及max的长度
6. 返回最终结果
class Solution {
    public String longestPalindrome(String s) {
        //当s的长度小于等于1,直接返回s,因为长度为1一定是回文串,为0是空串
        if(s.length() <= 1)
            return s;

        //动态规划的状态容器,用来判断dp[i][j]是不是回文子串
        boolean[][]dp = new boolean[s.length()][s.length()];
        //对状态容器进行初始化,当只有一个字符串的时候一定是回文子串
        for (int i = 0; i < s.length(); i++) {
            dp[i][i] = true;
        }

        int max = 1, start = 0;

        for(int j = 1; j < s.length(); j++){
            //之所以i<j。是因为dp矩阵中存放的是dp[i][j]是否是回文串,i>j不存在物理意义
            for(int i = 0; i < j && i < s.length()-1; i++){
                //此时首尾不一致,一定是false
                if(s.charAt(i) != s.charAt(j))
                    dp[i][j] = false;
                else{
                    if(j-i<=2)
                        dp[i][j] = true;
                    else
                        dp[i][j] = dp[i+1][j-1];
                }
                if(dp[i][j] && j-i+1>max){
                    max = j-i+1;
                    start = i;
                }
            }
        }
        return s.substring(start, start+max);
    }

}