给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 1:
输入: "aacecaaa"
输出: "aaacecaaa"
示例 2:
输入: "abcd"
输出: "dcbabcd"
解法1思路:因为是在前面加一个最少的数据,我们先想最笨的办法, 就是在abcd前面加上abcd的翻转,也就是变成dcbaabcd,这个肯定是回文的,
记录原字符串为s,翻转后的为rev_s,如果rev_s的后半部分和s的前半部分有一样的串,比如上面例子中的"a",那么新加进来的就可以省略这一部分
因为rev_s的后缀是s前缀的翻转,那么如果s的前缀有一个很长的回文串,那么只需要把回文串以外的部分反转之后放到s前面。
当然写法有很多种,直接n2时间复杂度找s的最长前缀回文串,或者找s的前缀和rev_s的后缀最长的相同长度,最终得解,这个的时间复杂度为n2
解法2:从解法一可以看出来其实是找s的前缀和rev_s的后缀最长的相同串,那么如果把s和rev_s拼起来,那么就是求这个new_s的前缀和后缀最长的相同长度,其实就是kmp算法设计next表的过程
因为考虑到在处理new_s的时候,可能会把s和rev_s混作一起,那么在这两个串之间加一个#
直接上代码,for循环部分,直接参考kmp
class Solution { public String shortestPalindrome(String s) { String rev = new StringBuilder(s).reverse().toString(); String new_s = s + "#" + rev; int len = new_s.length(); int[] f = new int[len]; f[0] = 0; for (int i = 1; i < len; i++) { int t = f[i - 1]; while (t > 0 && new_s.charAt(t) != new_s.charAt(i)) { t = f[t - 1]; } if (s.charAt(t) == new_s.charAt(i)) { t++; } f[i] = t; } return new StringBuilder(s.substring(f[len - 1])).reverse().toString() + s; } }