table of Contents
3.2 Center expansion algorithm
1, title
Given a string s
, to find s
the longest substring palindromic. You may assume that s
the maximum length of 1000.
2, Example
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
3, solutions
3.0 brute force
This should be when there is no other solution, you should think of: violence to solve, list all sub-strings, to determine whether a string is a palindrome, saving the longest palindrome string.
public static String longestPalindrome(String s) {
String ans = "";
int max = 0;
int len = s.length();
for (int i = 0; i < len; i++) {
for (int j = i + 1; j <= len; j++) {
String tmp = s.substring(i, j);
if (isPalindromic(tmp) && tmp.length() > max) {
ans = tmp;
max = j - i;
}
}
}
return ans;
}
private static boolean isPalindromic(String s) {
int len = s.length();
for (int i = 0; i < len / 2; i++) {
if (s.charAt(i) != s.charAt(len - i - 1)) {
return false;
}
}
return true;
}
Time complexity: two for loops to O (n²), for determining whether the loop inside palindromic O (n), so that the time complexity is O (n³).
Space complexity: O (1), constant variables.
3.1 Dynamic Programming
Violent solution time complexity is too high, we can consider, some violent solution to remove duplicate judge.
First define: string s to the subscript i of the string subscript j P (i, j), if the index i from s to string index j is palindromic sequence, then P (i, j) = true, otherwise P (i, j) = false. As shown below:
则 P(i, j) = (P(i + 1, j - 1) && s[i] == s[j])。
So if we want to know the case of P (i, j) does not need to call a function to determine palindromic strings, only need to know (i + 1, j-1) P can be the case, so that less time complexity the O (n). Therefore, we can use the method of dynamic programming, space for time, we have obtained the P (i, j) stored.
If s [i + 1, j-1] is a palindromic sequence, as long as s [i] == s [j], we can determine s [i, j] is a palindromic sequence.
note:
Seek length is 1 and a length of not formulated upper side when P (i, j) 2, as the experience we into the formula P [i] [j] in the i> where j, such as seeking P [1] [2], we need to know the P [1 + 1] [2-1] = P [2] [1], and P [2] [1] represents the S [2, 1] is not palindromic sequence, this is clearly wrong, so we need to judge alone.
Therefore, we first initialize the length of a palindromic sequence of P [i, j], using the equation so that the upper proposed P (i, j) = (P (i + 1, j-1) && S [i] == S [j]), then both sides of each outward extension of a character, a length of 3, 5, and all the odd-length on all seek out. Similarly, the length of palindromic sequence initialization 2 P [i, i + 1], using the formula, length of 4, all of even length 6 would all seek out.
public static String longestPalindrome(String s) {
int sLen = s.length();
int maxLen = 0;
String ans = "";
boolean[][] P = new boolean[sLen][sLen];
// 遍历所有长度
for (int len = 1; len <= sLen; len++) {
for (int start = 0; start < sLen; start++) {
int end = start + len - 1;
// 下标越界,结束循环
if (end >=sLen) {
break;
}
P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end);
if (P[start][end] && len > maxLen) {
maxLen = len;
ans = s.substring(start, end + 1);
}
}
}
return ans;
}
Time complexity: two cycles O (n²).
Space complexity: saving two-dimensional array with each sub-string PP case O (n²).
The following analysis of space usage :( to "babad" for example)
When we find the length of the case 5 of the sub-string, in fact only used the length of the case 4, and a length of 1 and 2 and the substring 3 where in fact no longer needed.
However, due to the cycle we are not done with the subscript P array, there is no method of optimizing think.
So we change the kinds of ideas, the same formula:
In fact, we can see from the recurrence formula, we first know i +1 will know i, so we only need to traverse backwards on the line.
public static String longestPalindrome(String s) {
int sLen = s.length();
String ans = "";
boolean[][] P = new boolean[sLen][sLen];
for (int i = sLen - 1; i >= 0; i--) {
for (int j = i; j < sLen; j++) {
P[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i < 2 || P[i + 1][j - 1]);
if (P[i][j] && j - i + 1 > ans.length()) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
Did not change the time complexity and space complexity and before, Can we look at optimizing space complexity.
When the i-th row seek when we only need the i + 1-line information, and if required j j-1 information, so as before j also need to reverse.
public static String longestPalindrome(String s) {
int sLen = s.length();
String ans = "";
boolean[] P = new boolean[sLen];
for (int i = sLen - 1; i >= 0; i--) {
for (int j = sLen - 1; j >= i; j--) {
P[j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || P[j - 1]);
if (P[j] && j - i + 1 > ans.length()) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
Time Complexity: constant O (n²).
Space complexity: reduced to O (n).
3.2 Center expansion algorithm
We know that certain palindromic sequence is symmetric, so we can select a center of each cycle, for about expansion, determines whether the character is equal to about.
Because the string of odd and even-numbered string exists, so we need to start from a extended characters, or between two characters from the beginning of the expansion, so a total of
n + (n-1) centers.
public static String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i+1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len-1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
public static int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return (R-1) - (L+1) + 1;
}
3.3 Manacher algorithm
https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html
4. Reference
https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html