214. 最短回文串 (JAVA)

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

 

示例 1:

输入:s = "aacecaaa"
输出:"aaacecaaa"
示例 2:

输入:s = "abcd"
输出:"dcbabcd"
 

提示:

0 <= s.length <= 5 * 10^4
s 仅由小写英文字母组成

 

解题思路:

首先想到先将待处理的字符串s翻转得到t,然后比较原字符串s和翻转字符串t,从第一个字符开始逐一比较,如果相等,说明s本身就是回文串,直接返回即可;如果不相等,s去掉最后一位,t去掉第一位,继续比较,以此类推直至有相等,或者循环结束,这样就能将两个字符串在正确的位置拼接起来了,但这种写法却会超时 TLE

class Solution {
public:
    string shortestPalindrome(string s) {
        string t = s;
        reverse(t.begin(), t.end());
        int n = s.size(), i = 0;
        for (i = n; i >= 0; --i) {
            if (s.substr(0, i) == t.substr(n - i)) {
                break;
            }
        }
        return t.substr(0, n - i) + s;
    }
};

改进:这里主要的小号是substring过多,改进方法是使用双指针来找出字符串s的最长回文前缀的大概范围。方法是指针i和j分别指向s串的开头和末尾,若 s[i] 和 s[j] 相等,则i自增1,j自减1,否则只有j自减1。需要注意的是,这样遍历一遍后,得到的范围 [0, i) 中的子串并不一定就是最大回文前缀,也可能还需要添加字符,举个例子来说,对于 "adcba",在 for 循环执行之后,i=2,可以发现前面的 "ad" 并不是最长回文前缀,其本身甚至不是回文串,需要再次调用递归函数来填充使其变为回文串,但可以确定的是可以添加最少的字符数让其变为回文串。而且可以确定的是后面剩余的部分肯定不属于回文前缀,此时提取出剩下的字符,翻转一下加到最前面,而对范围 [0, i) 内的子串再次递归调用本函数,这样,在子函数最终会组成最短的回文串,从而使得整个的回文串就是最短的。

class Solution {
    public String shortestPalindrome(String s) {
        //先找到完全没有重复出现的尾部字符串
        int i = 0, j = s.length() - 1;
        for(; j >= 0; j--){
            if(s.charAt(i) == s.charAt(j)) i++;
        }

        if(i == s.length()) return s;

        StringBuilder sb = new StringBuilder(s.substring(i));
        String r = sb.reverse().toString();
        //递归剩余的字符串
        return r + shortestPalindrome(s.substring(0,i)) + s.substring(i);
    }
}

其实这道题的最快的解法是使用 KMP 算法

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

 

posted on 2022-12-04 22:42  joannae  阅读(198)  评论(0编辑  收藏  举报

导航