Horse-drawn vehicles algorithm (Manacher's Algorithm)

This is the first book of pleasure and delight 343 update, the first 367 Pian original

Manacher's Algorithm, horse-drawn vehicle called the Chinese algorithm, is an algorithm person named Manacher proposed in 1975, to solve the problem is to find the longest palindrome substring, magic is the time complexity of the algorithm sophisticated to O(N), let's take a detailed idea of this algorithm.

01 Origin algorithm

When solving the problem palindromic longest substring, the current character is the general idea of ​​the center, left and right extensions thereto Looking palindromic, but the time of this solution is the complexity of O (N ^ 2), it can be time complexity and then reduce it? Do linear? Horse-drawn vehicles algorithm is the perfect solution to this problem.

02 Pretreatment

Palindromic its length string points, can be divided into odd palindromes (which length is an odd number), even palindromes (which length is an even number), generally need to find palindromic two cases, the algorithm drawn cart to simplify this step, the original strings have been processed, at left and right sides of each character are adding special characters (certainly not exist in the original string of characters), so that the string into an odd palindrome. E.g:

Original string: abba, a length of 4
after pretreatment: # a # b # b # a #, length 9

Original string: aba, a length of 3
Pretreatment: # a # b # a # , length of 7

03 calculates the length of the longest substring palindromic

String "cabbaf", for example, the new string pretreated "#c#a#b#b#a#f#"into a character array ARR, the definition of an auxiliary array int[] p, pthe length of arrequal length, p[i]expressed as arr[i]the longest character palindromic radius centered, p[i]=1indicates that only arr[i]the character itself back text string.

i       0 1 2 3 4 5 6 7 8 9 10 11 12
arr[i]  # c # a # b # b # a #  f  #
p[i]    1 2 1 2 1 2 5 2 1 2 1  2  1

Let's look at than to divide the relationship between the radius and the longest palindrome original string. In the above example, the longest substring is palindromic "#a#b#b#a#", it arr [6] as the center, the radius is 5, which represents the original string "abba", and "abba"a length of 4 can be obtained by subtracting 1 from 5, a string "cabbaf"the longest palindromic substring, then we are not able to obtain the relationship between the radius and the longest palindrome longest palindromic substring length?

Let us look at a few more examples, such as "aba", is converted "#a#b#a#"to a character 'b'-centric palindrome, radius 4, 3,3 minus 1 is the longest length of palindromic substring of the original string.

As another example "effe", the conversion is "#e#f#f#e#"to the middle of the most '#' is the center of the palindrome, radius 5, to give 4,4 minus 1 is the longest length of palindromic substring of the original string.

Thus, we finally obtain the relationship between the maximum radius and maximum palindrome palindromic substring length: int maxLength = p[i]-1. maxLengthIt represents the length of the longest substring palindromic.

04 calculates the longest substring starting index palindromic

Know the length of the longest palindrome substring, we also need to know the starting index value, so as to complete the interception of the longest palindrome substring.

In the third step to continue the string "cabbaf", for example, p[6]=5it is the longest radius, with 6 (i) by subtracting the maximum radius 5 (p [i]) to give 1, 1 and happens to be the longest substring palindromic "abba" the starting index.

Let us look at an example of odd palindrome. For example "aba", after a conversion "#a#b#a#", p [3] = 4, the maximum radius is 4, i is 3, 4 obtained by subtracting a i-1, the array subscript bounds.

In the case of an even palindrome, i cut up to meet the radius, while the odd palindromes but it will subscript out of bounds, we need to add a character in front of the string after the conversion, to solve the problem of cross-border index, it can not be '#', then add a '$'character of it, but after adding over a character, not an odd length of the string, and the character will not only be a plus recurring in the tail, for example '@', the length of this string is still odd, and meet in front conditions of the third portion.

Cadogan after a character, odd palindromes can do normal subtraction, and even palindrome it?

i       0 1 2 3 4 5 6 7 8 9 10 11 12 13
arr[i]  $ # c # a # b # b # a  #  f  #
p[i]      1 2 1 2 1 2 5 2 1 2  1  2  1

The fill character '$'after, p [7] = 5, i by subtracting the maximum radius, 7-5 = 2, and the result should be an ideal, it would be divided by two, so that one can get up. The odd palindrome "aba", minus the longest radius with i get is 0, divided by 2 or 0, can be the perfect solution to the problem of cross-border index.

Conclusion : palindromic longest substring starting index int index = (i - p[i])/2.

05 p array of computing

In the third step and the fourth step, we have used an array of key objects p, storage is the longest palindrome substring radius, then how did it come about?
Or in the example above, combined with the look,

i       0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
arr[i]  $ # c # a # b # b # a  #  f  #  @ 
p[i]      1 2 1 2 1 2 5 2 1 2  1  2  1

Set two variables MX and id, id palindromic substring all, can be extended to the center point of the rightmost position palindromic sub string, MX is the rightmost position of the string can be extended to a palindrome.

When i is equal to 7, ID is equal to 7, p [id] = 5, palindromic substring in the position of the center 7, the palindromic sequence is a sub-right boundary position 12.

When i is equal to 12, id is equal to 12, p [id] = 2, the position of the palindromic substring 12 in the center, the right border of the sub-palindromic sequence is position 14.

From this we can draw the relationship between the right and palindromic substring radius: mx = p[id]+id.

Because the strings are centrosymmetric palindrome, you know id center point, if a sub-location of the palindromic sequence to i as the center, and comprises the palindromic substring id to the center, i.e. mx > i, it will certainly be present in another j palindromic substring center, and i is the center in the sub-palindromic strings are equal and symmetrical, i.e. p[j] = p[i], id and i and j are centered symmetrically, i.e. i+j=2*id, if you know the value of i, then j = 2*id - i.

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, at this time p[i] = mx - i, p[j] = [pi]as for

Therefore, mx > iunder the p[i] = Math.min(p[2*id - i], mx - i)circumstances, .
Also, if i is greater than the mx, that is, behind the border substring mx, characters still need to compare calculated.

public static String Manacher(String s) {
    if (s.length() < 2) {
        return s;
    }
    // 第一步:预处理,将原字符串转换为新字符串
    String t = "$";
    for (int i=0; i<s.length(); i++) {
        t += "#" + s.charAt(i);
    }
    // 尾部再加上字符@,变为奇数长度字符串
    t += "#@";
    // 第二步:计算数组p、起始索引、最长回文半径
    int n = t.length();
    // p数组
    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 (t.charAt(j+p[j]) == t.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);
}


06 Summary

Horse-drawn vehicles algorithm for solving the longest palindromic substring complexity is reduced to O(N), although at the expense of part of the space, its spatial complexity O(N), but the trick of the algorithm is worth learning and reference.

Thematic algorithm has been continuous days more than six months , the algorithm of feature articles 211 + articles, public Number dialog box reply [ data structures and algorithms ], [ algorithm ], [ data structures either] in a keyword, to obtain a series of articles Collection .

That's all, if you have any good solution ideas, suggestions or other issues, you can exchange comments below, good-looking, message forwarding and support is the greatest reward for me!

Guess you like

Origin www.cnblogs.com/xiaochuan94/p/10971443.html