leetcode #5 Longest Palindromic

2017-07-05  本文已影响0人  huntriver

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example:
Input: "cbbd"
Output: "bb"

这道题有很多种解法。

首先在方法一中 我们要对奇数和偶数的情况区分对待。该算法巧妙的在每个字符之间加入了一个特殊字符(原串中没有出现过的即可)。这样我们只需要考虑奇数的情况了。举例说明: 假设原字符串为 babad, 我们再每个字符之间加入空格将其变成:‘!b!a!b!a!d!'. 不难发现,在新的字符串中的回文子串在旧的字符串中也是回文的。

Manacher 算法的核心是维护了一个一维数组 Radius[i],代表以第i个字符为中心的回文子串的半径。 举例说明:

字符串: ! b ! a ! b ! a ! d !
index : 0 1 2 3 4 5 6 7 8 9 10
Radius: 1 2 1 4 1 4 1 2 1 2 1

不难发现,最长的回文子串是max(Radius[i])-1.
为了高效的求出radius数组,该算法引入了两个变量maxIndex和maxRight. maxIndex 记录了到目前为止最长的回文子串的中心的索引坐标;maxRight记录了该最长回文子串最右的字符的坐标。

该算法是如何通过这两个变量得到当前i 的radius[i]呢?分为两种情况讨论:

再此基础上我们将radius[i] 向左右延展找到最大的以i为中心的子串,并且更新maxRight和maxIndex.

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
    let maxRight=0;
    let maxIndex=0;
    let radius=[];
    let maxLen=0;
    let ansIndex=0;
    let newString='!'+s.split('').join('!')+'!';
    for (let i=0;i<newString.length;i++){
        if (i<maxRight){
            radius[i]=min(maxRight-i,radius[maxIndex-(i-maxIndex)]);
        }
        else{
            radius[i]=1;
        }
        while (i-radius[i]>=0 && i+radius[i]<newString.length && newString[i-radius[i]]==newString[i+radius[i]]){ //向左右扩展
            radius[i]++;
        }
            
        if (radius[i]+i-1>maxRight){ 更新maxRight
            maxRight=radius[i]+i-1;
            maxIndex=i;
        }
        if (radius[i]>maxLen){ 记录最大值
            maxLen=radius[i];
            ansIndex=i;
           
        }
    }
    return  newString.substring(ansIndex-radius[ansIndex]+1,ansIndex+radius[ansIndex]).split('!').join('');;
};

function min(a,b){
    return a<b?a:b;
}

上一篇 下一篇

猜你喜欢

热点阅读