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.
[balabala] Method1从小到大逐一check不同长度的子串是否为回文,使用DP保存中间计算,但仍然会超时,Method3是非DP版的Method1,1年前的历史记录竟然是Accept的,估计当时leetcode 打瞌睡了。Method2 同样是DP,能够被Accept,分析计算次数和Method1一样,在Eclipse下实际运行超时的case,后者比前者快三、四ms,我认为差异主要是因为Method1 访问数组的模式不如Method2优,将二维数组看成一个矩阵,Method1 不断在各行间跳跃访问,而Method2 在一次外层循环中逐列访问同一行的数组。Method4是从当前1个字符或当前两个字符向两边辐射求得最长回文,该方法比Method2效率更高,因为它避免了一些无意义的计算,比如“abcdefg”, Method1和2均需要计算全部子串,而Method4不会计算诸如abcde这样的子串,在计算bcd时即停止计算其余以c为中心的子串。还有一种 O(n)的实现,还未看懂, http://www.cnblogs.com/tenosdoit/p/3675788.html 先备忘着。
[ref]
http://www.cnblogs.com/tenosdoit/p/3675788.html
http://www.cnblogs.com/jdflyfly/p/3810674.html
http://codeganker.blogspot.com/2014/02/longest-palindromic-substring-leetcode.html
// Method 1: O(n^2), time out public String longestPalindrome1(String s) { if (s == null || s.equals("")) return ""; int n = s.length(); boolean[][] dp = new boolean[n][n]; for (int i = 0; i < n; i++) dp[i][i] = true; String ans = s.substring(0, 1); for (int i = 0; i < n - 1; i++) { dp[i][i + 1] = s.charAt(i) == s.charAt(i + 1); if (ans.length() == 1 && dp[i][i + 1]) ans = s.substring(i, i + 2); } for (int l = 3; l <= n; l++) { for (int i = 0; i + l <= n; i++) { int j = i + l - 1; dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]; if (ans.length() < l && dp[i][j]) ans = s.substring(i, i + l); } } return ans; } // Method 2: O(n^2) 另一种DP实现 // http://codeganker.blogspot.com/2014/02/longest-palindromic-substring-leetcode.html public String longestPalindrome(String s) { if (s == null || s.equals("")) return ""; int n = s.length(); String ans = ""; int maxLen = 0; boolean[][] dp = new boolean[n][n]; for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { if (s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1])) { dp[i][j] = true; if (maxLen < j - i + 1) { maxLen = j - i + 1; ans = s.substring(i, j + 1); } } } } return ans; } // Method 3: O(n^2), from up to bottom, once accept, time out now public String longestPalindrome3(String s) { if (s == null || s.equals("")) return ""; int n = s.length(); for (int len = n; len >= 1; len--) { for (int i = 0; i + len <= n; i++) { String sub = s.substring(i, i + len); if (isPalin(sub)) { return sub; } } } return ""; } private boolean isPalin(String s) { int i = 0, j = s.length() - 1; while (i < j) { if (s.charAt(i) != s.charAt(j)) return false; i++; j--; } return true; } // Method 4: O(n^2) 以当前字符或者当前字符及下一个字符向外辐射找出最长的子串 // http://www.cnblogs.com/jdflyfly/p/3810674.html public String longestPalindrome4(String s) { if (s == null || s.equals("")) return ""; int n = s.length(); int maxLen = 1; int tmpLen = 0; String ans = s.substring(0, 1); for (int i = 0; i < n - 1; i++) { tmpLen = getPalin(s, i - 1, i + 1); if (tmpLen > maxLen) { int start = i - tmpLen / 2; ans = s.substring(start, start + tmpLen); maxLen = tmpLen; } tmpLen = getPalin(s, i, i + 1); if (tmpLen > maxLen) { int start = i - tmpLen / 2 + 1; ans = s.substring(start, start + tmpLen); maxLen = tmpLen; } } return ans; } private int getPalin(String s, int left, int right) { int n = s.length(); int len = right - left - 1; while (left >= 0 && right < n) { if (s.charAt(left--) == s.charAt(right++)) { len += 2; } else { return len; } } return len; }