leetcode-中级算法-数组和字符串-最长回文字串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

示例 1:
输入: “babad”
输出: “bab”
注意: "aba"也是一个有效答案。

示例 2:
输入: “cbbd”
输出: “bb”


思路

这道题很显然可以用暴力求解,但时间复杂度太高,也起不到刷题的训练作用。搜了一下,全是关于manacher的算法。看了好久才弄懂的。写这篇也是来巩固梳理一下(其他人写的好多代码很难懂!)希望读者有耐心读完!

理论

回文可能是奇数:‘aba’;也可能是偶数:‘abba’,最节省时间的判断回文方法是从中间开始向两边判断,但偶数个数的回文字符串就不行了。于是——Manacher就想到,在所有字符中间添加一个占位的符号(例如’#’,必须不是原始字符串中的字符),这样 ‘abba’ 就变为 ‘#a#b#b#a#’,就可以从中间的 ‘#’ 开始想两边延申啦。

所以,第一步就是将原始字符串 'abba' 变化为含有 '#' 的字符串 '#a#b#b#a#'
s = '#' + s.split('').join('#') + '#';

接下来,就要循环遍历了。以每个字符为中心,向两边延申直到不相等,延申长度为 radius,

第二步,设置变量:
let radius = 0;

还要设置一个最大半径,用来保存回文的最大半径,和保存最长子串的subString

let maxRadius = 0;
let subString = '';

当radius大于maxRadius时,说明该更新了,同时,要保存最长子串 subString

subString = s.slice(i - radius + 1, i + radius);

遍历完后,别忘了把子串中的所有’#’ 去掉

while (subString.includes('#')) {
    subString = subString.replace('#', '')
}

全部代码:

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
  s = '#' + s.split('').join('#') + '#';
  let radius = 0;
  let maxRadius = 0;
  let subString = '';
  
  for (let i = 0; i < s.length ; i ++) {
    radius = 1
    
    while (s[i - radius] === s[i + radius] && s[i - radius] !== undefined) {
      radius ++;
    }
    
    if (radius > maxRadius) {
      subString = s.slice(i - radius + 1, i + radius);
      maxRadius = radius;
    }
    
  }
  
  while (subString.includes('#')) {
    subString = subString.replace('#', '')
  }
  
  return subString;
};

PS:这是简单精简版!也能通过测试,原版的更加优化快速,但我已无力!

猜你喜欢

转载自blog.csdn.net/romeo12334/article/details/84034485
今日推荐