[leetcode] Shortest Palindrome 解题报告

题目链接:https://leetcode.com/problems/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".


思路:也是蛋疼的一题啊,刚开始用中心法求回文数的方法求前缀最大的回文数是多少,一直超时,时间复杂度为O(n*n),代码如下:

class Solution {
public:
    string shortestPalindrome(string s) {
        int len = s.size();
        if(len == 0)    return "";
        int left, right, i = (len*2 -1)/2 ;
        string result;
        int sum = 0;
        while(i >= 0)
        {
            sum++;
            left = i/2;
            right = i%2==1?(i/2+1):i/2;//奇偶数right指针位置不一样
            while(left >= 0)
            {
                if(s[left] == s[right])
                {
                    left--;
                    right++;
                }
                else
                    break;
            }
            if(left < 0)
                break;
            i--;
        }
        for(int i = len-1; i >= right; i--)
            result += s[i];
        result += s;
        return result;
    }
};

后来看了网上思路才知道应该用KMP来做,于是又折腾了好久KMP。推荐一篇文章吧: 从头到尾彻底理解 KMP。

本题其实是求最大的前缀和后缀的匹配数,例如字符串为abbad,可以看到我们只要在前面加一个d就能构成一个最短的回文数,因为其前缀abba是回文。现在我们的任务就是寻找最大回文前缀。

接下来我们将其逆转之后为dabba,再将其合并成一个字符串abbad$dabba,可以看出要求最大的回文前缀,只需要求出最大的前缀和后缀相等的长度。

这种时间复杂度为O(n),真是神奇的一个算法。

代码如下:

class Solution {
public:
    string shortestPalindrome(string s) {
        int len = s.size();
        if(len == 0)    return "";
        
        string revStr = s;
        reverse(revStr.begin(), revStr.end());
        string str =  s + "$" + revStr;
        vector<int> table(str.size(), 0);
        int index = 0;
        for(int i = 1; i< str.size(); i++)
        {
            if(str[index] == str[i])//如果当前匹配
            {
                table[i] = table[i-1]+1;
                index++;
            }
            else//如果当前不匹配
            {
                index = table[i-1];
                while(index > 0 && str[index] != str[i])//如果当前长度的不匹配,就缩短一位看是否匹配
                    index = table[index-1];
                if(str[i]==str[index])
                    index++;
                table[i] = index;
            }
        }
        int maxMatch = table[str.size()-1];
        string result = revStr.substr(0, len-maxMatch) + s;
        return result;
    }
};

参考:http://www.cnblogs.com/grandyang/p/4523624.html

https://leetcode.com/discuss/64309/clean-kmp-solution-with-super-detailed-explanation

你可能感兴趣的:(LeetCode,算法,KMP,回文数,palindrome)