214. 最短回文串
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 1:
输入: “aacecaaa”
输出: “aaacecaaa”
示例 2:
输入: “abcd”
输出: “dcbabcd”
思路
我们首先看实例可以看出目标串为原串的前面加上原串的逆序串的一部分,即abcd -> dcba abcd,从中间扩展,我们发现a和a是两个相同的子串,可以删除一个。
然后通过Rabin-Karp算法来计算逆序和正序的hash值和,当相同时,表示该位置内的字符在两个字符串相同,我们可以把逆序列的相同串给删除达到最优。
Rabin-Karp : hash[i] = (hash[i - 1] x base + ASCII(s[i])) % mod
逆序列的方程反推一下就有了
代码
class Solution {
public:
string shortestPalindrome(string s) {
int n = s.length();
int base = 128, mod = 1e9 + 7;
// left为正序列的hash和, right为逆序列的hash和, mul为逆序列hash的累乘,best为最优解的定位
int left = 0, right = 0, mul = 1, best = -1;
for(int i = 0; i < n; i++){
left = (s[i] + (long long)left * base) % mod;
right = ((long long)s[i] * mul + right) % mod;
if(left == right)
best = i;
mul = ((long long)mul * base) % mod;
}
string pre_s = s.substr(best + 1);
reverse(pre_s.begin(), pre_s.end());
return pre_s + s;
}
};