LeetCode 214. Shortest Palindrome
原题链接在这里:https://leetcode.com/problems/shortest-palindrome/
题目:
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.
For example:
Given "aacecaaa"
, return "aaacecaaa"
.
Given "abcd"
, return "dcbabcd"
.
题解:
求s前缀和 reverse s 后缀最长重合.
Time Complexity: O(n ^ 2).
Space: O(n).
AC Java:
1 class Solution { 2 public String shortestPalindrome(String s) { 3 if(s == null || s.length() == 0){ 4 return s; 5 } 6 7 int n = s.length(); 8 String rev = new StringBuilder(s).reverse().toString(); 9 for(int i = 0; i < n; i++){ 10 if(s.substring(0, n - i).equals(rev.substring(i))){ 11 return rev.substring(0, i) + s; 12 } 13 } 14 15 return rev + s; 16 } 17 }
其实求最短回文串,其实可以看作两个字符串求两串中的最长匹配字符,比如 串 “ abcd”
- 注意,由于这里一个串可以是回文串,所以此处的前缀和后缀应该分别加上最后一个和第一个字符
就是求“abcd”和反串”dcba“的前缀和后缀最大匹配长度
原始串 | 前缀 | 反转串 | 后缀 | 最大匹配 |
abcd | a ab abc abcd | dcba | a ba cba dcba | a |
由上面可以看出,abcd和dcba的最长匹配为a,一个字符,那么最后的回文串就是 反转串的长度4减去匹配长度1,得到3, 即反转串的前三个字符加上 原始串组成 ”abcabcd“
在KMP算法中曾今和相似的利用过最大前缀和后缀求next[]数组,如果我们这样看 将原始串S和反转串R形成一个新串New
S+#+反转 = abcd#dcba
Note: 这里之所以要加上#是为了防止p[New.length()-1]的值要大于s.length().
另外需要注意如下例子,产生了aabba, 如果不加"#", 前面和反转相加正好产生了一个很长的palindrome.
Input:"aabba"
Output:"aabba"
Expected:"abbaabba"
另外最后要加空格是因为next 把标记右移了一位,加空格是为了让这一位显现出来。
Time Complexity: O(n). Space: O(n).
AC Java:
1 public class Solution { 2 public String shortestPalindrome(String s) { 3 if(s == null || s.length() <=1){ 4 return s; 5 } 6 StringBuilder rev = new StringBuilder(s); 7 //add "#" 为了防止next后面的数字大于 s的长度,并且s本身能和后面产生palindrome, 如"aabba" 8 String mirror = s + "#" + rev.reverse().toString() + " "; 9 int [] next = new int[mirror.length()]; 10 getNext(mirror,next); 11 StringBuilder res = new StringBuilder(s.substring(next[next.length-1])); 12 return res.reverse().toString() + s; 13 } 14 private void getNext(String s, int [] next){ 15 next[0] = -1; 16 int k = -1; 17 int j = 0; 18 while(j<s.length()-1){ 19 if(k==-1 || s.charAt(k) == s.charAt(j)){ 20 k++; 21 j++; 22 next[j] = k; 23 }else{ 24 k=next[k]; 25 } 26 } 27 } 28 }
参考了这篇帖子:http://blog.csdn.net/yujin753/article/details/47047155