Shortest Palindrome@LeetCode（以及关于KMP的理解）

Shortest Palindrome

````java````public class Solution {
public String shortestPalindrome(String s) {
if (s == null || s.length() == 0 || s.length() == 1) return s;
int len = s.length(), tail = len;
StringBuilder builder = new StringBuilder();
while (1 < tail) {
if (isPalindrome(s.substring(0, tail))) {
builder = builder.append(s.substring(tail, len)).reverse();
break;
}
tail--;
}
if (builder.length() == 0) {
builder = builder.append(s.substring(tail, len)).reverse();
}
return builder.append(s).toString();
}

private boolean isPalindrome(String str) {
int len = str.length();
for (int i = 0; i < len / 2; i++) {
if (str.charAt(i) != str.charAt(len - i - 1))
return false;
}
return true;
}
}
``````

LeetCode做多了也就知道`O(n^2)`的算法必然有改进版，自己思考了下没有悟出来，就参考了这篇文章：[LeetCode] Shortest Palindrome 最短回文串

1. 求字符串`s`的翻转`s_rev`
2. 将两个字符串进行拼接：`{s}#{s_rev}`
3. 找出新字符串中最长公共前缀后缀长度`comLen`
4. `s_rev.substring(0, s.length() - comLen)`就是在原字符串头部插入的子串部分

1. `s[i]=s[j]`，也就是当前字符延续了之前的公共前缀后缀，那么`p[i]=p[i-1]+1`即可
2. `s[i]!=s[j]`，即`s.substring(0,j)``s.substring(i-j+1,i+1)`是不匹配的，但是仍然可能存在`s.substring(0,x)``s.substring(i-x+1,i+1)`，这一点就是我以前最不能理解的地方，这次结题的经历加深了我这部分的理解。

````java````public class Solution {
public String shortestPalindrome(String s) {
StringBuilder builder = new StringBuilder(s);
return builder.reverse().substring(0, s.length() - getCommonLength(s)) + s;
}

private int getCommonLength(String str) {
StringBuilder builder = new StringBuilder(str);
String rev = new StringBuilder(str).reverse().toString();
builder.append("#").append(rev);
int[] p = new int[builder.length()];
for (int i = 1; i < p.length; i++) {
int j = p[i - 1];
while (j > 0 && builder.charAt(i) != builder.charAt(j)) j = p[j - 1];
p[i] = j == 0 ? (builder.charAt(i) == builder.charAt(0) ? 1 : 0) : j + 1;
}
return p[p.length - 1];
}
}
``````

1.1k 声望
63 粉丝
0 条评论