leetcode214. 最短回文串/KMP

题目:214. 最短回文串

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

示例 1:

输入: "aacecaaa"
输出: "aaacecaaa"

示例 2:

输入: "abcd"
输出: "dcbabcd"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-palindrome
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

基本思想1:KMP

本题是在字符串的前面加上该字符串的后缀串的逆序,使得最终构成最短的回文串,也就是我们需要找到前缀串中最长的回文串。

如何寻找前缀串中最长的回文串?KMP

  • 将当前串的逆序作为查询串,当前串作为模式串,当查询串的指针指到最后时,模式串的指针所指的位置作为后缀串的起始位置

具体分析参考:官方题解

class Solution {
    
    
public:
    string shortestPalindrome(string s) {
    
    
        //KMP
        if(s.length() < 2)
            return s;
        string pattern = s;//模式串
        reverse(s.begin(), s.end());//查询串
        int pos = kmp(pattern, s);
        if(pos == s.length())//本身是回文串
            return s;
        string temp = pattern.substr(pos, pattern.length() - pos);
        reverse(temp.begin(), temp.end());
        string res = temp + pattern;
        return res;
    }
    int kmp(string pattern, string s){
    
    
        vector<int> next = fun(pattern);
        int i = 0, j = 0;
        int lens = s.size(), lenp = pattern.size();
        while(i < lens && j < lenp){
    
    
            if(j == -1 || s[i] == pattern[j]){
    
    
                ++i;
                ++j;
            }
            else{
    
    
                j = next[j];
            } 
        }
        return j;
    }
    vector<int> fun(string p){
    
    
        vector<int> res(p.length(), -1);
        int j = 0, k = -1;
        while(j < p.length() - 1){
    
    
            if(k == -1 || p[k] == p[j]){
    
    
                if(p[++k] == p[++j])
                    res[j] = res[k];
                else
                    res[j] = k;
            }
            else
                k = res[k];
        }
        return res;
    }
};

基本思想2:中心扩展(超时了)

从中间开始判断,以当前字符或者当前字符(一个中心)和当前字符左边的字符(两个中心)为中心进行求解。

class Solution {
    
    
public:
    int len;
    string shortestPalindrome(string s) {
    
    
        len = s.length();
        string res = "";
        if(len == 0)
            return res;
        int left, right;
        if(len % 2 == 0){
    
    
            right = len / 2;
            left = right - 1;
        }
        else{
    
    
            left = right = len / 2;
        }
        while(left >= 0 || right < len){
    
    
            if(left >= 0){
    
    
                fun(s, res, left - 1, left + 1);
                fun(s, res, left - 1, left);
                --left;
            }
            if(right < len){
    
    
                fun(s, res, right - 1, right + 1);
                fun(s, res, right - 1, right);
                ++right;
            }
            if(res.size())
                break;
        }
        return res;
    }
    void fun(string s, string &res, int l, int r){
    
    
            string temp, cur;
            while(l >= 0 && r < len){
    
    
                if(s[l] != s[r]){
    
    
                    break;
                }
                --l;
                ++r;
            }
            if(l == -1 && r == len)//本身就是回文
                res = s;
            if(l < 0 && r < len){
    
    //向左扩展
                temp = s.substr(r, len - r);
                reverse(temp.begin(), temp.end());
                cur = temp + s;
                if(res.size() == 0 || res.size() > cur.size())
                    res = cur;
            }
    }
};

猜你喜欢

转载自blog.csdn.net/qq_31672701/article/details/108295458