题目描述:
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 :
输入:s = "aacecaaa"
输出:"aaacecaaa"
提示:
0 <= s.length <= 5 * 104
s 仅由小写英文字母组成
链接:https://leetcode-cn.com/problems/shortest-palindrome/
分析:
最终的答案是什么样子呢?假设给s增加前缀为s1。
因为s1+s是回文的整体是回文的,所以s-s1的部分也是回文的,而添加的部分s1就是串s减去串s的最长回文前缀。
所以,这个问题就变成了如何求串s的最长回文前缀。
解法一:马拉车算法
马拉车算法可在O(n)时间内求出一个串的以各个位为中心的最大回文长度。
我们把串s跑一遍马拉车算法,然后找最长回文前缀的话就加个特判就好:这个回文中心 i 能扩展到第一个字符,也就是回文中心 i 的扩展长度是 i-1。
解法二:KMP算法
KMP算法也可以求出一个串的最长回文前缀。
next[i] 表示的就是前 i-1位的字符串的最长公共前后缀的长度。所以我们把s串倒序生成s1,然后s和s1合并,跑一遍KMP算法。
例如:串s为abacd,其倒序串s1为dcaba,合起来串为abacddcaba。可以看出其最长公共前后缀就是aba,也就是串s的最长回文前缀。
这里有特殊情况要注意,如果串s为aaa,那么其倒序串也为aaa,最终aaaaaa的最长公共前后缀5,,答案就不正确了。
所以我们在把s和s1合并的时候,中间加一个串s没有的特殊的分隔符,如#。这样出来的串是aaa#aaa,分隔符保证了其最长公共前后缀一定是在串s中。