一、题目

Given a string S, find the longest palindromic substring in S.

You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

Example

Given the string = "abcdzdcab", return "cdzdc".

Challenge

O(n2) time is acceptable. Can you do it in O(n) time.

求一个字符串中的最长回文子串。

二、解题思路

区间类动态规划

Time O(n^2), Space O(n^2)

dp[i][j]来存DP的状态,需要较多的额外空间: Space O(n^2)

DP的4个要素

  • 状态:
    • dp[i][j]: s.charAt(i)到s.charAt(j)是否构成一个Palindrome
  • 转移方程:
    • dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1])
  • 初始化:
    • dp[i][j] = true when j - i <= 2
  • 结果:
    • maxLen = j - i + 1;,并得到相应longest substring: longest = s.substring(i, j + 1);

中心扩展

这种方法基本思想是遍历数组,以其中的1个元素或者2个元素作为palindrome的中心,通过辅助函数,寻找能拓展得到的最长子字符串。外层循环 O(n),内层循环O(n),因此时间复杂度 Time O(n^2),相比动态规划二维数组存状态的方法,因为只需要存最长palindrome子字符串本身,这里空间更优化:Space O(1)。

三、解题代码

区间DP,Time O(n^2) Space O(n^2)

  1. public class Solution {
  2. /**
  3. * @param s input string
  4. * @return the longest palindromic substring
  5. */
  6. public String longestPalindrome(String s) {
  7. if(s == null || s.length() <= 1) {
  8. return s;
  9. }
  10. int len = s.length();
  11. int maxLen = 1;
  12. boolean [][] dp = new boolean[len][len];
  13. String longest = null;
  14. for(int k = 0; k < s.length(); k++){
  15. for(int i = 0; i < len - k; i++){
  16. int j = i + k;
  17. if(s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1])){
  18. dp[i][j] = true;
  19. if(j - i + 1 > maxLen){
  20. maxLen = j - i + 1;
  21. longest = s.substring(i, j + 1);
  22. }
  23. }
  24. }
  25. }
  26. return longest;
  27. }
  28. }

Time O(n^2) Space O(1)

  1. public class Solution {
  2. /**
  3. * @param s input string
  4. * @return the longest palindromic substring
  5. */
  6. public String longestPalindrome(String s) {
  7. if (s.isEmpty()) {
  8. return null;
  9. }
  10. if (s.length() == 1) {
  11. return s;
  12. }
  13. String longest = s.substring(0, 1);
  14. for (int i = 0; i < s.length(); i++) {
  15. // get longest palindrome with center of i
  16. String tmp = helper(s, i, i);
  17. if (tmp.length() > longest.length()) {
  18. longest = tmp;
  19. }
  20. // get longest palindrome with center of i, i+1
  21. tmp = helper(s, i, i + 1);
  22. if (tmp.length() > longest.length()) {
  23. longest = tmp;
  24. }
  25. }
  26. return longest;
  27. }
  28. // Given a center, either one letter or two letter,
  29. // Find longest palindrome
  30. public String helper(String s, int begin, int end) {
  31. while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) == s.charAt(end)) {
  32. begin--;
  33. end++;
  34. }
  35. return s.substring(begin + 1, end);
  36. }
  37. }