5. Longest Palindromic Substring

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.

一刷

  1. Manacher's Algorithm

Java: Manacher: Time Complexity - O(n), Space Complexity - O(n)

preprocess,将输入字符串s等间距插入特殊字符'#',目的是为了以后计算方便,不用太多考虑长度的奇偶性,不preprocess其实也可以
char[] t代表经过preprocess以后的transformed string
int[] p, p[i]是length of longest Palindromic string centerred at i,就是以i为中心,最长Palindromic string的长度
mirror代表以当前的center为中心,坐标i在center左边的镜像。因为 i - center = center - mirror,所以mirror = 2 * center - i。
下面比较重要的一点就是Manacher's Algorithm最主要的性质, 这里利用了之前计算过的最长的Palindromic String。假设之前计算过一个很长很长的Palindromic String,其中心在center, 那么我们遍历当前center的后面的元素 i 的时候,假如这个i在之前那个很长的Palindromic String的右边界范围内,那么我们就可以得到一个公式来节约重新匹配 - p[i] = Math.min(p[mirror], right - i), 即 p[i] 的当前最小值等于 p[mirror] 和 right - i这两个值中的较小者。 这里p[mirror]是以这个mirror为中心的最长回文字符串的长度。
就比如"#a#b#a#a#b#a#",假如当前的center在两个"a"中间的"#",假设我们正计算以之后那个"a"为中心的结果, 因为之前的p[mirror]等于2,所以这里p[i]至少等于2和right - i中的较小者。
假如我们正计算第二个"b"为中心的结果,因为之前的p[mirror]等于4,所以p[i]至少等于4和right - i中的较小者。
有了p[mirror]和right - i这两个边界,我们就可以节约许多的重复matching
上一步确定了p[i]的最小值以后,我们就可以继续进行尝试扩展当前Palindromic。这个时候我们没有取巧的办法,只能在t中对t[i + p[i]]和t[i - p[i]]进行逐字符对比,假如他们相同,则我们增加p[i]的长度,直到求出以i为中心的最长回文串长度
在上一步找出了以i为中心的最长回文串长度后,我们比较一下当前字符串的右边界是否大于历史最长回文串右边界"right",假如当前回文串更长,则我们更新center = i, 新的右边界right = p[i] + i。
这里我们就完成了p[i]的计算,也就是我们得到了每个以i为中心的最长回文字符串的长度。 这个时候我们再遍历一遍数组,找到其中最长的那一个,然后再对原始字符串进行substring操作就可以了

public class Solution {
    
    public String longestPalindrome(String s) {
        if(s == null || s.length == 0) return s;
        char[] t = new char[s.length()*2 + 1]; // transformed string
        int[] p = new int[t.length]; // p[i] is length of longest Palindromic string centered at i
        preprocess(s, t);
        int center = 0, right = 0;
        
        for(int i=1; i=0 && t[i + p[i]] == t[i - p[i]]){
                p[i]++;
            }
            if(i + p[i] > right){
                center = i;
                right = i+p[i];
            }
        }
        
        center = 0;
        int maxLen = 0;
        for(int i=1; i maxLen){
                center = i;
                maxLen = p[i];
            }
        }
        
        return s.substring((center - p[center] + 2)/2, (center + p[center])/2);
    }
    
    private void preprocess(String s, char[] t){
        for(int i=0; i

二刷
题解:下面的思路是选palindrome的中心点,并以中心点扩展。

public class Solution {
private int lo, maxLen;

public String longestPalindrome(String s) {
    int len = s.length();
    if (len < 2)
        return s;
    
    for (int i = 0; i < len-1; i++) {
        extendPalindrome(s, i, i);  //assume odd length, try to extend Palindrome as possible
        extendPalindrome(s, i, i+1); //assume even length.
    }
    return s.substring(lo, lo + maxLen);
}

private void extendPalindrome(String s, int j, int k) {
    while (j >= 0 && k < s.length() && s.charAt(j) == s.charAt(k)) {
        j--;
        k++;
    }
    if (maxLen < k - j - 1) {
        lo = j + 1;
        maxLen = k - j - 1;
    }
}}

你可能感兴趣的:(5. Longest Palindromic Substring)