LeetCode 214. 最短回文串(字符串hash || KMP)

最短回文串
题意:求最长回文前缀。

  • 字符串hash
    求出字符串hash之后倒序遍历即可。
#define ull unsigned long long 
class Solution {
    
    
public:
    static const int P = 1e9+7;
    vector<ull> h1,h2,p{
    
    1};
    string shortestPalindrome(string s) {
    
    
        int n = s.size(), len = 0;
        h1.resize(n+10),h2.resize(n+10),p.resize(n+10);
        for(int i=1;i<=n;i++){
    
    
            p[i] = p[i-1]*P;
            h1[i] = h1[i-1]*P+(s[i-1]-'A'+1);
        }
        for(int i=n;i>=1;i--) h2[i] = h2[i+1]*P+(s[i-1]-'A'+1);
        for(int i=n;i>=1;i--){
    
    
            if( h1[i] == h2[1]-h2[ i+1]*p[i] ){
    
    
                len = i;
                break;
            }
        }
        string t = s.substr(len,n-len);
        reverse(t.begin(),t.end());
        return t+s;
    }
};
  • KMP
    将原来的串作为pattern串,它的逆转作为text串。
    然后求出文本串以最后一个字符结尾的串能和pattern串的前缀匹配的长度。
    这就是一开始那个串的最长回文前缀。
class Solution {
    
    
public:
    vector<int> next;
    string shortestPalindrome(string s) {
    
    
        string p = s;
        reverse(s.begin(),s.end());
        int n = s.size(), j = 0, len = 0;
        next.resize(n+2,0);
        for(int i=2;i<=n;i++){
    
    
            while(j>0 && p[i-1]!=p[j]){
    
    
                j = next[j];
            }
            if(p[i-1]==p[j]){
    
    
                j++;
            }
            next[i] = j;
        }
        j = 0;
        for(int i=1;i<=n;i++){
    
    
            while(j>0 && (j==n || s[i-1]!=p[j])){
    
    
                j = next[j];
            }
            if(s[i-1]==p[j]){
    
    
                j++;
            }
        }
        len = j;
        string t = s.substr(0,n-len);
        return t+p;
    }
};

一个更加巧妙的做法,直接把字符串的逆转加到原始串的后面,中间加上分割符,跑出next数组。然后最长公共前后缀就是我们要求的最长回文前缀。

class Solution {
    
    
public:
    vector<int> next;
    string shortestPalindrome(string s) {
    
    
        string p = s;
        reverse(s.begin(),s.end());
        s = p+"#"+s;
        int n = s.size(), j = 0, len = 0;
        next.resize(n+2,0);
        for(int i=2;i<=n;i++){
    
    
            while(j>0 && s[i-1]!=s[j]){
    
    
                j = next[j];
            }
            if(s[i-1]==s[j]){
    
    
                j++;
            }
            next[i] = j;
        }
        len = j;
        string t = s.substr(p.size()+1,p.size()-len);
        return t+p;        
    }
};

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/108290490