最長迴文字串

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. 語文很差,表述更差,若有理解不到位的地方,請指出
相關文章
相關標籤/搜索