Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.
Example 1:
Input: "aacecaaa"Output: "aaacecaaa"
Example 2:
Input: "abcd"Output: "dcbabcd"
题意
给定一个字符串s,要求在它前面添加字符,使得到的新字符串为回文串,且长度最短。
思路
在原字符串s中找到以左端点为开头的最长回文子串,将s中剩余的右半部分逆置后放在原字符串之前,得到的一定是最短的回文串,如图:
所以问题就转化为了找到原字符串中左侧的最长回文子串。
常规方法用的时间即可找到回文子串。另有两种
复杂度的方法:
Manacher马拉车算法:具体解析详见博客园 - BIT祝威
KMP:待完善
代码实现 - Two Pointers
class Solution {public String shortestPalindrome(String s) {int maxLength = 1;for (int i = s.length(); i >= 1; i--) {if (isPalindrome(s.substring(0, i))) {maxLength = i;break;}}StringBuilder sb = new StringBuilder();for (int i = s.length() - 1; i >= maxLength; i--) {sb.append(s.charAt(i));}sb.append(s);return sb.toString();}private boolean isPalindrome(String s) {int left = 0, right = s.length() - 1;while (left < right) {if (s.charAt(left++) != s.charAt(right--)) {return false;}}return true;}}
代码实现 - Manacher马拉车算法
class Solution {public String shortestPalindrome(String s) {int maxLen = findMaxPalinLength(s);StringBuilder sb = new StringBuilder();for (int i = s.length() - 1; i >= maxLen; i--) {sb.append(s.charAt(i));}sb.append(s);return sb.toString();}private int findMaxPalinLength(String s) {String t = transform(s);int[] p = new int[t.length()];int C = 0; // 中心位置int R = 0; // 右边界int maxLen = 0; // 回文串最大半径for (int i = 0; i < t.length(); i++) {int j = 2 * C - i; // j是i关于C的对称点p[i] = R >= i ? Math.min(p[j], R - i) : 0; // 分三种情况进行赋值// 回文半径可能增加的情况while (i + p[i] + 1 < t.length() && i - p[i] - 1 >= 0 && t.charAt(i + p[i] + 1) == t.charAt(i - p[i] - 1)) {p[i]++;}// 找到以左端点为起点的最长回文字串if (i - p[i] == 0 && p[i] > maxLen) {maxLen = p[i];}// 更新中心点和右边界if (i + p[i] > R) {C = i;R = i + p[i];}}return maxLen;}// 字符串转换private String transform(String s) {StringBuilder sb = new StringBuilder();for (int i = 0; i < s.length(); i++) {sb.append('#').append(s.charAt(i));}sb.append('#');return sb.toString();}}
代码实现 - KMP
