1. 程式人生 > 實用技巧 >【LeetCode】214. 最短迴文串

【LeetCode】214. 最短迴文串

題目連結

214. 最短迴文串

題目描述

給定一個字串 s,你可以通過在字串前面新增字元將其轉換為迴文串。找到並返回可以用這種方式轉換的最短迴文串。

示例 1:
輸入: "aacecaaa"
輸出: "aaacecaaa"

示例 2:
輸入: "abcd"
輸出: "dcbabcd"

解題思路

1.常規思路

找出字串s中所有以s[0]為起點的迴文字串中最長的那一個迴文字串,那剩餘的元素逆序拼接至開頭即可。

2.KMP演算法

參考題解

將原字串翻轉,並加在原串後。由於迴文串翻轉後不變,因此字首的迴文串就等於字尾的迴文串(公共前後綴)

,即求next陣列的值。

AC程式碼

1.常規思路

class Solution {
    public String shortestPalindrome(String s) {
        char[] cs = s.toCharArray();
        if (cs.length <= 1) {
            return s;
        }
        int index = 0;
        for (int i = 0; i <= (cs.length - 1) / 2; i++) {
            index = Math.max(index, palindrome(cs, i));
        }

        if (index == cs.length) {
            return s;
        }
        StringBuilder sb = new StringBuilder(s);
        return new StringBuilder(s.substring(index + 1, cs.length)).reverse().append(sb).toString();
    }

    private int palindrome(char[] cs, int i) {
        int res = 0;
        if (isPalindrome1(cs, i)) {
            res = 2 * i;
        }
        if (isPalindrome2(cs, i)) {
            res = 2 * i + 1;
        }
        return res;
    }

    // aba情況迴文子串
    private boolean isPalindrome1(char[] cs, int i) {
        for (int j = 0; j < i; j++) {
            if (cs[j] != cs[2*i - j]) {
                return false;
            }
        }
        return true;
    }

    // abba情況迴文子串
    private boolean isPalindrome2(char[] cs, int i) {
        if (i >= cs.length / 2) {
            return false;
        }
        for (int j = 0; j <= i; j++) {
            if (cs[j] != cs[2*i + 1 - j]) {
                return false;
            }
        }
        return true;
    }
}

2.KMP演算法

class Solution {
public:
    int commpute_next(string pattern){
        vector<int>next(pattern.size() + 1, 0);//next的陣列大小必須是pattern字串長度+1,這樣才能算出最長公共前後綴的			//長度
        next[0] = -1;
        next[1] = 0; // A沒有前後綴
        int i = 2; // i表示next陣列的索引
        int k = 0;
        while (i < next.size()) {
            if (pattern[i - 1] == pattern[k]) { // pattern索引比next索引小1
                next[i] = k + 1;
                k = next[i];
                ++i;
            } else if (k == 0){
                next[i] = 0;
                ++i;
            } else{
                k = next[k];
            }
        }
        return next[next.size() - 1];
    }

    string shortestPalindrome(string s) {
        if(s == ""){
            return "";
        }
        string reverse = "";
        for (int i = s.size() - 1; i >= 0; --i) {
            reverse += s[i];
        }
        
        string pattern = s + '#' + reverse;
        int max_len = commpute_next(pattern);//max_len含義:最長公共前後綴的長度
        return reverse.substr(0, reverse.size() - max_len) + s;
    }
};