leetcode 214. Shortest Palindrome(最短回文串)

给一个字符串 S, 你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

例如:

给出 “aacecaaa”,返回 “aaacecaaa”。

给出 “abcd”,返回 “dcbabcd”。

因为只能在串首添加字符串,解题的思路比较好想:
令res = s.reverse,找到res的最大后缀suffix,其中suffix=s的前缀prefix,那么答案就是
s.reverse-suffix+s

public String shortestPalindrome(String s) {
        if(s.length() < 1){
            return s;
        }
        int len = s.length();
        String res = new StringBuilder(s).reverse().toString();
        for(int i=0;i<len;i++){
            if(res.substring(i,len).equals(s.substring(0,len-i))){
                return new StringBuilder(res).append(s.substring(len-i,len)).toString();
            }
        }
        return new StringBuilder(res).append(s.substring(0,len)).toString();
    }

但是 testcase有一个很长的全a字符串,以上解法会超时,要通过此case,还是要通过kmp算法快速找到res的最大后缀suffix,然后求得解,kmp算法实现看:这里

 private void getLPS(String s, int[] lps){
        // i是后缀末尾的指针,j是前缀末尾的指针
        int j = 0, i = 1;
        lps[0] = 0;
        // 从j=0,i=1开始找,错开了一位
        while(i < s.length()){
            // 如果字母相等,则继续匹配,最长相同前后缀的长度也加1
            if(s.charAt(i) == s.charAt(j)){
                lps[i] = j + 1;
                i++;
                j++;
            // 如果不同
            } else {
                // 如果前缀末尾指针还没退回0点,则找上一个子前缀的末尾位置
                if(j != 0){
                    j = lps[j - 1];
                // 如果退回0点,则最长相同前后缀的长度就是0了
                } else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
    }

    public String shortestPalindrome(String s) {
        if(s.length() < 1){
            return s;
        }
        int len = s.length();
        String rev = new StringBuilder(s).reverse().toString();
        int next[] = new int[len*2+1];
        getLPS( new StringBuilder(s).append("#").append(rev).toString(), next);
        return new StringBuilder(rev.substring(0,len-next[next.length-1])).append(s).toString();
    }

你可能感兴趣的:(LeetCode)