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"

思路

最简单直接的方法是 brute force,即先求以起始索引为开始位的最长回文字串,然后将剩下的部分逆置直接加到s前即可。这种方法比较耗时,可以使用KMP算法来解这题。

KMP算法

将s和其逆转字符串r连接起来,这肯定是一个回文,在他们中间加一个其它字符构成新的字符串t,然后还需要一个和t长度相同的一位数组next,其中next[i]表示从t[i]到开头的子串的相同前缀后缀的个数,就是KMP算法中的那个next数组。最后把不相同的个数对应的字符串添加到s之前即可。其实和brute force一样都是找以起始索引为开始位的最长回文字串,只不过现在不是遍历各个字符去找,而是利用KMP算法去找。找到后直接将原字符串s除了这个回文字串剩下的部分逆置后加到s前面即可。

下面next数组的计算过程可以参照KMP算法解释连接中最大长度表部分。

对于next[i-1],加入索引i位置上的字符得到的0~i的字串情况next[i]是如何变化的呢?原来的所有前缀不变,但是多了个前缀,即原来的最长前缀加上i-1位置上的的字符。原来的后缀都要发生变化,因为最后面的字符改掉了,所以原来的所有后缀要加上i位置上的字符,另外还多出了一个后缀,即位置i上的单个字符。

如果next[i-1]是0,即没有匹配的前后缀,那么加上位置i上的字符后前缀后缀也是不匹配的。但是有一种可能会增加前缀后缀的公共最长元素,那就是原来的起始索引处的字符可能等于新加入的i索引位置上的字符,若相等则next[i]=1,否则还是0。

假如next[i-1]不是0,则其值是0到索引i-1位置上的字串中前缀后缀的最大公共元素长度(能够匹配的最长前缀后缀,且注意前缀一直是从0开始的,这样的话最长前缀加上其长度就是其在前后缀比较过程中不匹配的字符索引位置)。

next[i] -- 0~i处匹配的最长前缀后缀的长度。

代码

解释

public String shortestPalindrome(String s) {
String temp = s + "#" + new StringBuilder(s).reverse().toString();
int[] table = getTable(temp); //get the maximum palin part in s starts from 0
return new StringBuilder(s.substring(table[table.length - 1])).reverse().toString() + s;
} public int[] getTable(String s){
//get lookup table
int[] table = new int[s.length()]; //pointer that points to matched char in prefix part
int index = 0;
//skip index 0, we will not match a string with itself
for(int i = 1; i < s.length(); i++){
if(s.charAt(index) == s.charAt(i)){ //一开始i=1,index=0,比较s[0]和s[1],如果相等那么table[1]=1,index=1
//we can extend match in prefix and postfix
table[i] = table[i-1] + 1; //
index ++;
}else{
       //因为index指向table[i-1]的最长匹配前缀的末位置字符,如果这个字符不等于位置i上的字符则断定原来的最长前缀肯定不匹配任何后缀(因为后缀以末字符为尾)
       //假设原来的最长匹配前缀是s[0~2],那么可以得出s[0~3],s[0~4]这些比最长匹配前缀要长的前缀肯定是不匹配后缀的,而新的后缀无非就是后面加了个字符,
       //那么这些前缀肯定也不能匹配新的后缀,但是如果原来i-1位置上的字符等于i位置上的字符而index这时指向的是i-1位,则便是上面if的情形
       //table[i]表示在s[0~i]中匹配的最长前缀的末字符位置,如果table[5]=2则表示s[0~5]中匹配的最长前缀是s[0~2],让index来指向这个末位置字符。
index = table[i-1];
while(index > 0 && s.charAt(index) != s.charAt(i)){
          //we will try to shorten the match string length until we revert to the beginning of match (index 1)
index = table[index-1];
} //when we are here may either found a match char or we reach the boundary and still no luck
//so we need check char match
if(s.charAt(index) == s.charAt(i)){
//if match, then extend one char
index ++ ;
}
table[i] = index;
}
} return table;
}

LeetCode214. Shortest Palindrome的更多相关文章

  1. [Swift]LeetCode214. 最短回文串 | Shortest Palindrome

    Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  2. [LeetCode] Shortest Palindrome 最短回文串

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  3. LeetCode 214 Shortest Palindrome

    214-Shortest Palindrome Given a string S, you are allowed to convert it to a palindrome by adding ch ...

  4. Shortest Palindrome

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  5. Java for LeetCode 214 Shortest Palindrome

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  6. 【leetcode】Shortest Palindrome(hard)★

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  7. LeetCode Shortest Palindrome

    原题链接在这里:https://leetcode.com/problems/shortest-palindrome/ 题目: Given a string S, you are allowed to ...

  8. 214. Shortest Palindrome

    题目: Given a string S, you are allowed to convert it to a palindrome by adding characters in front of ...

  9. 【Leetcode】Shortest Palindrome

    Shortest Palindrome Given a string S, you are allowed to convert it to a palindrome by adding charac ...

随机推荐

  1. 在 C Level 用 dlopen 使用 第三方的 Shared Library (.so)

    http://falldog7.blogspot.com/2013/10/android-c-level-dlopen-shared-library-so.html 在 Android 裡,撰寫 JN ...

  2. Hadoop Yarn事件处理框架源码分析

    由于想在项目中使用类似yarn的事件处理机制,就看了实现.主要是由Dispatcher.java,EventHandler.java,Service.java这3个类撑起来的. 在事件处理之前,先注册 ...

  3. Selenium判断获取的元素是否可见(display:none)

    在爬虫中需要自动登陆并判断是否登陆成功,如果登陆错误的话还需要知道错误提示信息,此时需要判断提示信息是否可见 if self.element_exist_xpath('//*[@id="bu ...

  4. 子字符串substring 问题 - KMP 字符串匹配算法备忘录

    本文为自己对KMP的理解. 对KMP很好的介绍可以参考 http://www.cnblogs.com/yjiyjige/p/3263858.html 本文为对这篇文章的提炼和补充. KMP算法基本思想 ...

  5. 我的CCF备考指南

    CCF计算机软件能力认证(简称CCF CSP认证). 认证涉及知识点: 认证内容主要覆盖大学计算机专业所学习的程序设计.数据结构.算法以及相关的数学基础知识.包括但不限于: (1)程序设计基础 逻辑与 ...

  6. ES6中函数的扩展

    一.设置默认参数 ES6之前,给函数设置默认参数是这样做的: function fn(a) { if(typeof y === undefined){ a = a || 'hello'; } cons ...

  7. SpringMVC中 Session的使用情况

    在SpringMVC中,使用Session可以用通过两种方式 1.servlet-api 即HttpSession session.setAttritute(),session.getAttribut ...

  8. 51nod 1873 高精度计算

    JAVA BigDecimal import java.util.*; import java.math.*; public class Main { public static void main( ...

  9. LightOJ 1129 - Consistency Checker Trie树模板

    题意:给出n条串判断是否存在一个串为另一个串的前缀. 思路:套Trie树的模板,先全部插入,再查找每个字串,如果查找字串完毕,但还存在下一个节点,说明存在前缀. /** @Date : 2016-11 ...

  10. mysql 创建视图

    1.单表创建视图 例如:创建一个选择语句,选出学生的编号,姓名和考号 //创建一个视图名字为stu_view1选择 来自数据表student中的id,name 和kn 中的数据 create view ...