5.最长回文子串

public class Solution {

    /**
     * 寻找字符串中的最长回文子串(动态规划解法)
     * @param s 输入字符串
     * @return 最长回文子串
     */

     /*
     回文的核心特征是 对称性。一个字符串要成为回文,必须满足:
     1.首尾字符相同
     2.去掉首尾后的子串仍然是回文
     */
    public String longestPalindrome(String s) {
        // ====== 特殊情形处理 ======
        int len = s.length();
        if (len < 2) {
            return s; // 长度0或1时直接返回自身
        }

        // ====== 初始化记录变量 ======
        int maxLen = 1;   // 当前发现的最长回文长度(最小值为1)
        int begin = 0;    // 最长回文的起始索引

        // ====== DP表格初始化 ======
        // dp[i][j]表示s的子串[i..j]是否为回文
        boolean[][] dp = new boolean[len][len];  // 默认值false
        char[] charArray = s.toCharArray();      // 转为字符数组便于快速访问
        
        // 初始化单字符回文(所有长度为1的子串都是回文)
        for (int i = 0; i < len; i++) {
            dp[i][i] = true; // 对角线置为true
        }

        // ====== 动态规划填表 ======
        for (int j = 1; j < len; j++) {       // 右边界j从1开始
            for (int i = 0; i < j; i++) {      // 左边界i始终小于j
                /* 情况1:首尾字符不同 */
                if (charArray[i] != charArray[j]) {
                    dp[i][j] = false;
                } 
                /* 情况2:首尾字符相同 */
                else {
                    /* 子串长度判断(关键优化):
                       - 长度2/3的子串(i,j相邻或间隔1个字符)
                       - 此时首尾相同即构成回文 */
                    if (j - i < 3) { 
                        dp[i][j] = true;
                    } 
                    /* 长度>3的子串:状态转移 */
                    else {
                        // 当前子串是否是回文 = 内部子串是否是回文
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                /* 发现更长回文时更新记录 */
                if (dp[i][j] && (j - i + 1 > maxLen)) {
                    maxLen = j - i + 1;  // 计算当前回文长度
                    begin = i;           // 记录起始位置
                }
            }
        }
        
        // ====== 返回结果 ======
        return s.substring(begin, begin + maxLen);
    }
}
posted @ 2025-05-17 15:06  星星永远发着光  阅读(9)  评论(0)    收藏  举报