力扣刷题日记-5. 最长回文子串

55 阅读1分钟

给你一个字符串 s,找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

思路:
    1. 每个下标为中心点往两边扩
    1. 但是回文里面如果再套回文,那么大回文两边的小回文直径是一样的,所以可以减少一些计算量来加速
    1. 如果大回文左侧的回文超出了边界,那么大回文右侧的小回文最多是R-i
/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function (s) {
    if (!s || s.length == 0) return ''
    let str = manacherString(s)
    let pArr = new Array(str.length).fill({}).map(_ => {
        return {
        len: 0,
        palindrome: ''
        }
    }), C = -1, R = -1, max = 0;
    for (let i = 0; i < str.length; i++) {
        pArr[i].len = R > i ? Math.min(pArr[2 * C - i].len, R - i) : 1;
        while (i + pArr[i].len < str.length && i - pArr[i].len > -1) {// 如果不符合就超出两端,结束
            if (str[i + pArr[i].len] == str[i - pArr[i].len]) {
                pArr[i].palindrome = str.slice(i - pArr[i].len,
                i + pArr[i].len + 1)
                pArr[i].len++;

            } else {
                break;
            }

        }
        if (i + pArr[i].len > R) {
            R = i + pArr[i].len;
            C = i;
        }
        max = Math.max(max, pArr[i].len)
    }
    pArr.sort((a, b) => b.len - a.len)
    let ans = pArr[0].palindrome.filter(i => {
        return i != '#'
    })
    // return max - 1;
    return ans.join('')
};
function manacherString(str) {
    let strArr = str.split('');
    let res = new Array(strArr.length * 2 + 1)
    let index = 0;
    for (let i = 0; i < res.length; i++) {
        res[i] = (i & 1) == 0 ? '#' : strArr[index++]
    }
    return res
}