Horse-drawn vehicles algorithm (Manacher's Algorithm)
EDITORIAL
In general when searching the longest substring palindromic, by more extended center solution , this solution is time complexity of O (n ^ 2), the horse-drawn vehicles sophisticated algorithm to the time complexity O (n), is an algorithm person named Manacher proposed in 1975.
1- Pretreatment
Original string '#' separator, the same characters and does not increase in end to end.
E.g:
原始字符串:abba -->字符串长度为:4
将字符串以‘#’分离:#a#b#a#b# -->字符串长度为:9
首尾增加不相同的字符:$#a#b#a#b#^ -->字符串长度为:11
原始字符串:ersds -->字符串长度为:5
将字符串以‘#’分离:#e#r#s#d#s# -->字符串长度为:11
首尾增加不相同的字符:$#e#r#s#d#s#^ -->字符串长度为:13
The string "#" isolated: the length of the string object are converted to an odd number.
And last increase is not the same character: The aim is to stop setting conditions traversal, because ending characters are the same as any other character.
2- calculated longest substring length palindromic
Definition of two containers: arr [], p [] , and a variable I
ARR [] characters in all records, p [] is recorded in the center of each character is the longest radius palindrome
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
arr[] $ # a # b # a # b # c # b # a # e # ^
p[] 1 1 2 1 2 1 4 1 2 1 6 1 2 1 2 1 2 1 1
# One more character than the original interval since all have increased the original string '#' symbol, which increases
the number of characters is increased after # 1 minus the number of characters equal to the initial string
Thus, we finally obtain the relationship between the maximum radius and maximum palindrome palindromic substring length: int maxLength = p [i] -1. maxLength represents palindromic longest substring length.
If you do not take a few examples may be appreciated that authentication: int maxLength = p [i] -1
3- calculating the longest substring starting index palindromic
Because separators are increased #, # it will be present in the end positions of the substring palindromic
equal to the number of sides of the palindromic substring of characters and number #
E.g:
当i=5时,此时回文子串为#,回文子串的左侧为:$#a#b
当i=6时,此时回文子串为#b#a#b#,回文子串的左侧为:$#a
其中:回文子串左侧的字符数量 = 回文子串的左侧长度 / 2
And because the length of the left side may be acquired by palindromic substring ip [i],
then: the number of sub-strings palindromic the left = (ip [i]) / 2
Therefore: palindromic longest substring starting index of int index = (i - p [ i]) / 2.
If you do not take a few examples may be appreciated that authentication: int index = (i - p [i]) / 2.
4- calculation array p
2,3 two steps are used in an array of p, p array is how come it? We also need the other two variables id and MX
id is a palindrome substring center, mx is a palindrome substring rightmost position limit
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
arr[] $ # a # b # a # b # c # b # a # e # ^
p[] 1 1 2 1 2 1 4 1 2 1 6 1 2 1 2 1 2 1 1
当i=6时,id=6, mx=10,那么p[id] = mx -id = 4
当i=7时,id=7, mx=8,那么p[id] = mx -id = 1
当i=8时,id=8, mx=10,那么p[id] = mx -id = 2
Because palindromic substring is centrally symmetric, known central positions symmetrical id, if a palindromic substring of i as the center, and comprises the palindromic substring in id as the center, i.e. mx> i, then there will certainly be another j is a central palindromic substring, and i is the center in the sub-palindromic strings are equal and symmetrical, i.e., p [j] = p [i], i and j are the id is symmetrical, i.e., i + j = 2id, If you know the value of i, then j = 2id - i.
例如:当id= 6,i = 8 时,
根据:j = 2*id - i,计算得:j = 4.
反之:当id= 6,i = 4 时,计算得:j = 8.
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
arr[] $ # a # b # a # b # c # b # a # e # ^
p[] 1 1 2 1 2 1 4 1 2 1 6 1 2 1 2 1 2 1 1
But we need to consider another case, if there is a palindrome with i-centered substring, still have mx> i, but with i-centered palindrome substring over the right border mx, the i's to this mx back substring in the text, and the other end of the palindromic symmetry to j substrings centered or equal, in which case p [i] = mx - i, p [j] = [pi], as for the child outside the right border sequence mx , i that is centered outside the palindromic substring whether the portion satisfies the above condition or the need to traverse the comparison character.
Thus, in the mx> i, where, p [i] = Math.min ( p [2id - i], mx - i).
Also, if i is greater than the mx, that is, behind the border substring mx, characters still need to compare calculated.
The sample code
public class Test {
public static void main(String[] args) {
String nums = "ababcbae";
String s = longestPalindrome2(nums);
System.out.println("符合条件的集合为:"+s);
}
public static String preProcess(String s) {
int n = s.length();
if (n == 0) {
return "^$";
}
String ret = "^";
for (int i = 0; i < n; i++)
ret += "#" + s.charAt(i);
ret += "#$";
return ret;
}
// 马拉车算法
public static String longestPalindrome2(String s) {
//预处理字符串
String str = preProcess(s);
int n = str.length();
int[] p = new int[n];
int id = 0, mx = 0;
// 最长回文子串的长度
int maxLength = -1;
// 最长回文子串的中心位置索引
int index = 0;
for (int j=1; j<n-1; j++) {
p[j] = mx > j ? Math.min(p[2*id-j], mx-j) : 1;
// 向左右两边延伸,扩展右边界
while (str.charAt(j+p[j]) == str.charAt(j-p[j])) {
p[j]++;
}
// 如果回文子串的右边界超过了mx,则需要更新mx和id的值
if (mx < p[j] + j) {
mx = p[j] + j;
id = j;
}
// 如果回文子串的长度大于maxLength,则更新maxLength和index的值
if (maxLength < p[j] - 1) {
maxLength = p[j] - 1;
index = j;
}
}
// 截取字符串,输出结果
int start = (index-maxLength)/2;
return s.substring(start, start + maxLength);
}
}