最短回文串

给定一个字符串 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;
    }
}
原文地址:https://www.cnblogs.com/tobemaster/p/12927687.html