LeetCode----5. 最长回文子串

 题目

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。

示例 2:

输入:s = “cbbd”
输出:“bb”

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

 java

要找到字符串中最长的回文子串,可以使用动态规划或中心扩展的方法。下面是一个使用中心扩展的Java代码示例:

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1) {
            return "";
        }
        
        int start = 0, end = 0;
        
        for (int i = 0; i < s.length(); i++) {
            int len1 = expandAroundCenter(s, i, i);
            int len2 = expandAroundCenter(s, i, i + 1);
            int len = Math.max(len1, len2);
            
            if (len > end - start) {
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }
        
        return s.substring(start, end + 1);
    }
    
    private int expandAroundCenter(String s, int left, int right) {
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
        return right - left - 1;
    }
}

这个代码使用了中心扩展的思想,遍历字符串中的每个字符,以每个字符为中心向两边扩展,找到以该字符为中心的最长回文子串。然后,比较每个字符为中心的回文子串,找到最长的那个。

最终返回最长回文子串。这个算法的时间复杂度为O(n^2),其中n是字符串的长度。

 java 代码2

Manacher算法是一种用于查找最长回文子串的高效算法,其核心思想是利用已知的回文子串信息来加速查找。下面是对Manacher算法的具体题解:

  1. 预处理:Manacher算法的第一步是将原始字符串预处理,将问题简化为处理奇数长度的回文串。这是通过在每个字符之间插入特殊字符(通常是“#”)来实现的。

  2. 初始化:创建一个新的字符串,用于预处理后的字符串。同时,创建一个数组p,用于存储以每个字符为中心的回文子串的半径长度。

  3. 遍历:从预处理字符串的第一个字符开始,依次处理每个字符。在遍历的过程中,维护两个变量centerright,它们表示当前找到的最长回文子串的中心和右边界。

  4. 中心扩展:以每个字符为中心,尝试向左右两侧扩展,以查找回文子串。在扩展的过程中,使用mirror变量来查找对称位置的字符,从而可以更快地计算回文子串的半径。

  5. 更新centerright:如果当前回文子串的右边界超过了right,则更新centerright。这样,算法可以在查找下一个回文子串时利用已知信息。

  6. 寻找最长回文子串:在遍历的同时,记录最长回文子串的半径长度和中心位置。

  7. 最终结果:根据最长回文子串的信息,计算原始字符串中的起始位置和结束位置,从而得到最长回文子串。

以下是Manacher算法的Java代码

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1) {
            return "";
        }
        
        // 预处理字符串,插入特殊字符,使字符串的长度为奇数
        String transformedString = preProcess(s);
        int n = transformedString.length();
        int[] p = new int[n];  // 用于存储回文子串的半径长度
        int center = 0, right = 0;  // 当前找到的最长回文子串的中心和右边界
        
        for (int i = 1; i < n - 1; i++) {
            int mirror = 2 * center - i;  // 查找对称位置的字符
            
            if (right > i) {
                p[i] = Math.min(right - i, p[mirror]);  // 初始值是已知的回文子串信息
            }
            
            // 尝试扩展回文子串
            while (transformedString.charAt(i + p[i] + 1) == transformedString.charAt(i - p[i] - 1)) {
                p[i]++;
            }
            
            // 如果回文子串的右边界扩展超过了 right,更新 center 和 right
            if (i + p[i] > right) {
                center = i;
                right = i + p[i];
            }
        }
        
        int maxLen = 0;
        int centerIndex = 0;
        
        // 寻找最长回文子串的半径长度和中心位置
        for (int i = 1; i < n - 1; i++) {
            if (p[i] > maxLen) {
                maxLen = p[i];
                centerIndex = i;
            }
        }
        
        // 计算原始字符串中的起始位置和结束位置
        int start = (centerIndex - maxLen) / 2;
        int end = start + maxLen;
        
        return s.substring(start, end);
    }
    
    // 预处理函数,将原始字符串转换为用于Manacher算法的格式
    private String preProcess(String s) {
        int n = s.length();
        if (n == 0) {
            return "^$";
        }
        
        StringBuilder sb = new StringBuilder("^");
        
        for (int i = 0; i < n; i++) {
            sb.append("#").append(s.charAt(i));
        }
        
        sb.append("#$");
        return sb.toString();
    }
}

你可能感兴趣的:(LeetCode,leetcode,算法)