最长回文子串

67 阅读1分钟

最长回文子串

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

示例 1:

输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。 示例 2:

输入:s = "cbbd" 输出:"bb"

提示:

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

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
​
};
  • 方法一(暴力解法):

  • 方法二(中心扩散):

    function longestPalindrome(s: string): string {
        let Resleft = 0;
        let Resright = 0;
        let maxLen = 0;
        
        let i = 0; //设i为中心的索引
        while(i < s.length) {
            let left = i - 1;
            while (left >= 0 && s[i] === s[left]) {
                left--;
            }
            let right = i + 1;
            while (right < s.length && s[i] === s[right]) {
                right++;
            }
            const end = right; //这里的right是右边第一个跟中心s[i]不相等的字符索引,保存下来,等会i直接跳到end处,可减少重复中心的计算
            while (left >= 0 && right < s.length && s[left] === s[right]) {
                left--;
                right++;
            }
            if (maxLen < right - left - 1) {
                maxLen = right - left - 1;
                Resleft = left + 1;
                Resright = right - 1;
            }
            i = end; 
        }
        return s.substring(Resleft, Resright + 1);
    };
    
  • 方法三(动态规划):

    var longestPalindrome = function(s) {
        let len = s.length
        let maxLen = 1
        let start = 0
        let dp = Array.from(new Array(len), ()=> new Array(len).fill(false))
    ​
        for(let l = 2 ; l <= len ; l ++){
            // 字串的长度,字符串长度从 2 开始
            for(let i = 0 ; i < len ; i ++){
                // i 起始的位置
                // j 为终止位置
                let j = i + l - 1
                // 初始条件
                if((l == 2 || l == 3) && s[i] == s[j]){
                    dp[i][j] = true
                }
    ​
                // 递推公式
                if(s[i] === s[j] && dp[i + 1][j - 1] == true){
                    dp[i][j] = true
                }
    ​
                if(dp[i][j] && l > maxLen){
                    maxLen = l;
                    start = i
                }
            }
        }
    ​
        return s.substr(start , maxLen)
    };
    
  • 方法四(Manacher 算法):

    class Solution {
        public String longestPalindrome(String s) {
            int start = 0, end = -1;
            StringBuffer t = new StringBuffer("#");
            for (int i = 0; i < s.length(); ++i) {
                t.append(s.charAt(i));
                t.append('#');
            }
            t.append('#');
            s = t.toString();
    ​
            List<Integer> arm_len = new ArrayList<Integer>();
            int right = -1, j = -1;
            for (int i = 0; i < s.length(); ++i) {
                int cur_arm_len;
                if (right >= i) {
                    int i_sym = j * 2 - i;
                    int min_arm_len = Math.min(arm_len.get(i_sym), right - i);
                    cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
                } else {
                    cur_arm_len = expand(s, i, i);
                }
                arm_len.add(cur_arm_len);
                if (i + cur_arm_len > right) {
                    j = i;
                    right = i + cur_arm_len;
                }
                if (cur_arm_len * 2 + 1 > end - start) {
                    start = i - cur_arm_len;
                    end = i + cur_arm_len;
                }
            }
    ​
            StringBuffer ans = new StringBuffer();
            for (int i = start; i <= end; ++i) {
                if (s.charAt(i) != '#') {
                    ans.append(s.charAt(i));
                }
            }
            return ans.toString();
        }
    ​
        public int expand(String s, int left, int right) {
            while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
                --left;
                ++right;
            }
            return (right - left - 2) / 2;
        }
    }
    ​