最长回文字串

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

方法一

  • 每个字母,用双指针查询最长回文
  • 区分奇偶:惟一区别 k = i 或者 k = i + 1
var longestPalindrome = function (s) {
    let res = '';
    for (let i = 0; i < s.length; i++) {
        for (let j = i, k = i; j >= 0 && k < s.length && s[j] === s[k]; j-- , k++) {
            if (res.length < k - j + 1) res = s.substr(j, k - j + 1);
        }
        for (let j = i, k = i + 1; j >= 0 && k < s.length && s[j] === s[k]; j-- , k++) {
            if (res.length < k - j + 1) res = s.substr(j, k - j + 1);
        }
    }
    return res;
};
复制代码

方法二:Manacher算法

  • 马拉车局限性太大,只适用于最长回文字串,不建议学习 ma na cher 马拉车名字来源

leetcode 地址

s字符串奇偶问题,加入#解决

奇回文串数组

aba 
#a#b#a#
复制代码

偶回文串缓存

abba
#a#b#b#a#
复制代码

变量

  • id: 容纳节点i最大回文子串的中心位置
  • mx: 上一个对称轴+它的回文半径
  • p: 回文半径数组

核心代码分析

  1. p[i] = mx > i ? Math.min(p[2 * id - i], mx - i) : 1;

解释:学习

  • mx > i,说明i在上一个元素回文半径内,那i就对应一个j
  • 经过对称性获得对称点j = 2 * id - i
    • 验证:id = 3, i = 4, j = 2, j = 2 * 3 - 4 = 2
  • p[2 * id - i],是j的对称半径,mx - i 是 以i对对称中心的对称半径
  • 比较Math.min(p[2 * id - i], mx - i)
  • p[2 * id - i] > mx - i, 说明j的对称半径大于了mx,即超过了mx,只能截取mx以内的,便是mx-i
  • 反之p[2 * id - i] < mx - i,说明j的回文半径在mx以内,所以p[i]p[2 * id - i]
  • p[i]确定是回文的,而后左右判断,是否回文,再++
  • 经过对称性,拿到j的回文半径,至关于用了缓存临时变量
  1. p[i] + i > mx
  • 保留最大的回文半径的对称点赋值id,上一个回文对称点+回文半径mx

代码

function longestPalindrome(s) {
    let str = s.split('').reduce((prev, item) => prev + item + '#', '#');
    let id = 0, mx = 0, p = [];
    let newLen = str.length;
    // p = [x,x] 存的index的回文半径,mx 是上一个元素+回文半径
    for (let i = 0; i < newLen; i++) {
        p[i] = mx > i ? Math.min(p[2 * id - i], mx - i) : 1;
        // i + p[i] 与 i - p[i], 左右对比,p[i]做为一个变量增加
        // 控制左右是否溢出
        while (
            str[i + p[i]] === str[i - p[i]] 
            && i - p[i] >= 0 
            && i + p[i] < newLen
        ) { p[i]++ }
        if (p[i] + i > mx) {
            id = i;
            mx = id + p[i];
        }
    }
    const c_index = p.findIndex(it => Math.max(...p) === it);
    const s_str = str.slice(c_index - (p[c_index] - 1), c_index + p[c_index]);
    return s_str.replace(/\#/g, '');
}
复制代码

注意点:ui

  1. 我存数组长度是,用let size = str.length,关键字在leetcode里面报内部错误,😓
  2. 语文很差,表述更差,若有理解不到位的地方,请指出
相关文章
相关标签/搜索