LeetCode 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".

Credits:
Special thanks to @ifanchu for adding this problem and creating all test cases. Thanks to @Freezen for additional test cases.

先来个直接的,就是求出从字符串起始处开始的最长回文串,如果有这样的回文串存在(必然存在,单个字符就是一个回文串,但找到的回文串长度越长,补全后的回文串整体长度就越小),我们只需要以这个找到的回文串为中心,再在字符串前补全即可。但是TLE

class Solution {
public:
    string shortestPalindrome(string s) {
        int len = s.size();
        int idx;
        for (idx=len; idx>0; idx--) {
            if (isPar(s, 0, idx)) {
                break;
            }
        }
        string mirror;
        for (int i=len - 1; i>=idx; i--) {
            mirror.push_back(s[i]);
        }
        return mirror + s;
    }
    
    bool isPar(string& s, int start, int end) {
        int p = start;
        int q = end - 1;
        while (p < q) {
            if (s[p] != s[q]) {
                return false;
            }
            p++, q--;
        }
        return true;
    }
};

一样的思路,别人的就简洁很多 ,92ms

class Solution {
public:
    string shortestPalindrome(string s) {
        string s2=s;
        reverse(s2.begin(),s2.end());
        int n=s.size(),l;
        for(l=n;l>=0;l--)
        {
            if(s.substr(0,l)==s2.substr(n-l))
                break;
        }
        return s2.substr(0,n-l)+s;
    }
};

 还是一样的思路,但是加入高效求回文串的过程(manacher's algorithm,见另一篇自己博客图解,网上资料也很多),时间8ms,速度提高太多了

class Solution {
public:
    string shortestPalindrome(string s) {
        string ss("$");
        for (int i=0; i<s.size(); i++) {
            ss.push_back(s[i]);
            ss.push_back('$');
        }
        
        int len = ss.size();
        vector<int> pl(len, 1);
        
        int far = 0;
        int mid = 0;
        int longest = 0;
        int mirror = 0;
        
        for (int i=0; i<len; i++) {
            int cfar = i;
            
            // if this index is covered by exist palindrome
            if (far > i) {
                mirror = 2 * mid - i;
                cfar = min(pl[mirror], far - i) + cfar;
            }
            // spread out
            while (cfar < len && (2 * i - cfar >= 0) && ss[cfar] == ss[2 * i - cfar]) {
                cfar++;
            }
            // current palindrome single part length(incuded middle character)
            pl[i] = cfar - i;
            
            // update right farest index covered by palindrome
            if (cfar > far) {
                mid = i;
                far = cfar;
            }
            // is this palindrome start from s[0]?
            if (2 * i - cfar == -1) {
                // index i in ss is just the palindrome length in s(original string)
                longest = i;
            }
        }
        
        string str = s.substr(longest);
        reverse(str.begin(), str.end());
        
        return str + s;
    }
};

 discuss里还有用KMP做的,不过KMP不熟,以后再写。

改写一下:

class Solution {
public:
    string shortestPalindrome(string s) {
        if (s.size() < 2) {
            return s;
        }
        int plen = palindrome(s);
        string left = s.substr(plen);
        reverse(left.begin(), left.end());
        return left + s;
    }
    
    int palindrome(string& s) {
        string ms(s.size() * 2 + 1, '$');
        int i = 0;
        for (char ch : s) {
            ms[i++ * 2 + 1] = ch;
        }
        int mlen = ms.size();
        vector<int> lens(mlen, 0);
        
        int far = 0;
        int lcenter = 0;
        
        int maxlen = 2;
        for (int i=0; i<mlen; i++) {
            int p = i, q = i;
            if (i < far) {
                int mirror = 2 * lcenter - i;
                int step = min(lens[mirror], far - i);
                p -= step;
                q += step;
            }
            while (p >= 0 && q < mlen && ms[p] == ms[q]) {
                p--, q++;
            }
            if (q > far) {
                far = q;
                lcenter = i;
            }
            lens[i] = q - i;
            if (p < 0) {
                maxlen = max(maxlen, lens[i]);
            }
        }
        return (maxlen * 2 - 1) / 2;
    }
};
原文地址:https://www.cnblogs.com/lailailai/p/4575362.html