[Problem]
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.
[Analysis]
这题的思路有很多种,网上也有各种讨论。这里我采用的是个人觉得比较好理解的一种利用Dynamic Programming求解的方法,时间和空间复杂度都是O(n^2)。dp[i][j]记录的是从i到j的子串是否为palindromic,base case是i >= j时为true。然后对每个位置求解从i开始长度为k的子串是否为palindromic。
对于s[i...j]有两种情况:
1. s[i] != s[j],则dp[i][j] = false;
2. s[i] == s[j], 则dp[i][j] = dp[i + 1][j - 1]
注意在嵌套循环求解的过程中k在外循环,也就是每次循环实际是对每个位置求解k长度的子串是否palindromic,这样保证了在求解dp[i][j]时dp[i + 1][j - 1]已经有解。
另一种比较简单的思路是对每个可能的中心点计算以其为中心的最长回文字串的长度。这样的中心点有N - 1 + N = 2N个,时间复杂度也是O(n^2)。Manacher‘s Algorithm可以得到最优的时间复杂度O(n),但比较难理解。
参考:
LeetCode(5) Longest Palindromic Substring: http://blog.csdn.net/feliciafay/article/details/16984031
Longest Palindromic Substring Part II: http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
[Solution]
public class Solution { public String longestPalindrome(String s) // Dynamic Programming solution { if(s.length() == 0) { return ""; } if(s.length() == 1) { return s; } /* * dp denotes if a substring s[i .. j] is a palindromic */ boolean[][] dp = new boolean[s.length()][s.length()]; int i,j; /* * initialize dp */ for( i = 0; i < s.length(); i++) { for( j = 0; j < s.length(); j++) { if(i >= j) { /* * if i == j, it is a palindromic substring of length 1; * if i > j, regard it as an empty substring when initializing. */ dp[i][j] = true; } else { /* * otherwise, initialize to false */ dp[i][j] = false; } } } int k; int maxLen = 1; int start = 0, end = 0; for(k = 1; k < s.length(); k++) { /* * test if an substring starts from s[i] of length k is palindromic * note that we have the base case when k = 1 it is always palindromic */ for(i = 0; k + i < s.length(); i++) { j = i + k; if(s.charAt(i) != s.charAt(j)) { dp[i][j] = false; } else { dp[i][j] = dp[i+1][j-1]; if(dp[i][j]) { if(k + 1 > maxLen) { maxLen = k + 1; start = i; end = j; } } } } } return s.substring(start, end + 1); } }