您的位置:首页 > 其它

Shortest Palindrome -- leetcode

2015-08-19 11:08 176 查看
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"
.

算法一:

先找出字符串S最大的回文串,该回文串的特点,左边界与S左边界同。

故问题转化为,求出该回文串的右边界。

然后将右边界后面的字符反转加到S前面,即为题目所求。

由于回文串的特点为,反转后,得到的新串与原串相等。

则将S串,整体反转后得到一个新串RS。

则题目进一步转化为,求S串的最大前缀,且该前缀与RS的后缀相等。

在leetcode上实际执行时间为96ms。

class Solution {
public:
    string shortestPalindrome(string s) {
        string rev(s.rbegin(), s.rend());
        int size = s.size();
        for (; size > 0; --size) {
            if (s.substr(0, size) == rev.substr(rev.size()-size, size))
                break;
        }
        return rev.substr(0, rev.size()-size) + s;
    }
};


算法二,KMP前缀法

算法一,其实不够效率。

求出最大的 前缀且与后缀相等,可以寻求KMP帮助。

KMP建立next数组过程,就是一个不断求出当前子串中,最大的前缀和后缀相等问题。

这里,我们S字符串,和其反转后得到新字符串RS,并在中间加入一个分隔字符,合并成一个新的字符串。从而问题就可以用KMP方法解决。

之所以加入分隔字符,是为了防止前缀和后缀有重叠部分。

此处,我们所感兴趣的next数组中最后一个值。

即,合并后的新串中,最大前缀与后缀的长度。

在leetcode上实际执行时间为16ms。远好于算法一。

class Solution {
public:
    string shortestPalindrome(string s) {
        if (s.empty()) return s;
        string kmp = s + "#" + string(s.rbegin(), s.rend());
        vector<int> next(kmp.size()+1);
        int j = -1;
        next[0] = j;
        for (int i=0; i<kmp.size();) {
            while (j>=0 && kmp[i]!=kmp[j])
                j = next[j];
            
            ++i;
            ++j;
            next[i] = j;
        }

        string suffix = s.substr(next.back());
        return string(suffix.rbegin(), suffix.rend()) + s;
    }
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: