[LeetCode-JAVA] Shortest Palindrome

题目:

Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.

For example:

Given "aacecaaa", return "aaacecaaa".

Given "abcd", return "dcbabcd".

题意:在原字符串的前面加上若干字母,使其形成回文,返回其中最短的。

思路1:最开始的思路,总后往前扫面,如果[o - i]可以形成回文,则将n后面的reverse并且添加到s的前面即可,这样做勉强可以AC,但显然是最差的算法。

代码1(AC时间850ms左右):

public class Solution {
    public String shortestPalindrome(String s) {
        for(int i=s.length();i>=1;i--)
            if(isPalindrome(s.substring(0, i)))
                return new StringBuilder(s.substring(i)).reverse()+s;
        return "";
    }
    static boolean isPalindrome(String s){
        int left=0,right=s.length()-1;
        while(left<right)
            if(s.charAt(left++)!=s.charAt(right--))
                return false;
        return true;
    }
}

思路2:和思路1差不太多,考虑是否可以用不同的方式进行判断,只是判断回文的方式不同,采取中心点的方式,可以作为一种想法,但效果和1差不多。

代码2(AC时间800ms左右):

public class Solution {
    public String shortestPalindrome(String s) {
        if(s == null || s.length() < 2)
            return s;
        int index = 0;
        for(int i = 0 ; i < s.length()*2-1 ; i++){
            int left = i/2;
            int right = i/2;
            if(i%2 == 1)
                right++;
            if(helper(s, left, right)){
                index = (i%2 == 1 ? right*2 : right*2+1);
            }
        }
        
        return new StringBuilder(s.substring(index)).reverse() + s;
    }
    
    private boolean helper(String s, int left, int right) {
        while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            left--;
            right++;
        }
        if(left == -1)
            return true;
        return false;
    } 
}

思路3(推荐思路):利用曼彻斯特算法,其中利用dp来保存已有的结果,进行大幅度的加速。

在曼彻斯特回文判断中,加入判断,因为题目最主要是要找到包含第一个字符的回文,因此在循环的过程中,当最长子回文包含第一个字符的时候,将索引更新,最后将回文后面的部分reverse之后添加到s前面即可。

代码3(AC时间300ms左右):

public class Solution {
    public String shortestPalindrome(String s) {
        if(s == null || s.length() < 2)
            return s;
        int len = s.length();
        int n = len * 2 + 3;
        char[] toCharry = new char[n];
        toCharry[0] = '$';
        toCharry[1] = '#';
        for(int i = 0 ; i < s.length() ; i++){
            toCharry[2*i + 2] = s.charAt(i);
            toCharry[2*i + 3] = '#';
        }
        toCharry[n-1] = '!';
        
        int[] p = new int[n];
        
        int in = 0;
        int mx = 0;
        int maxpi = 0;
        int maxin = 0;
        
        for(int i = 1 ; i < n-1 ; i++){
            if(i < mx)
                p[i] = Math.min(mx - i, p[2*in - i]);
            else
                p[i] = 1;
            while(toCharry[i + p[i]] == toCharry[i - p[i]]) p[i]++;
            if(p[i] + i > mx){
                mx = i + p[i];
                in = i;
            }
            if(p[i] > maxpi && in == p[in]){
                maxpi = p[i];
                maxin = in;
            }
        }
        StringBuilder sb = new StringBuilder();
        for(int i = maxin+p[maxin] ; i < n-1 ; i += 2){
            sb.append(toCharry[i]);
        }
        
        return sb.reverse() + s;
    }
}

参考链接:http://www.felix021.com/blog/read.php?2040

       http://m.blog.csdn.net/blog/xc889078/10858041

原文地址:https://www.cnblogs.com/TinyBobo/p/4587142.html