Palindromic longest substring algorithm --Manacher

Manacher algorithm, known as "horse car" algorithm, can solve the problem of the length of the longest palindromic substring of a string at the time complexity is O (n) case.

First, the general solution palindromic substring

The idea is simple each character string as a substring of the palindromic symmetry center point, each stored maximum value with the previously determined palindromic substring, the length is the longest palindromic the resulting substrings, such embodiment of the time complexity is O (n ^ 2). In the solution process, the base palindrome palindromic substring substring even number is not the same. For example the longest substring palindromic ABA, B is the center of symmetry, if the longest substring palindromic Abba, the center of symmetry between the two B should, in order to solve this problem, a symbol can be added on both sides of each character, What specific symbol (which is a string of symbols as well) has no effect on the results, such as with "#", then the two sequences described above into a # a # b # a # and # a # b # b # a #, determined lengths of 6 and 9, divided by 2 to get the final result will be 3 and 4. In this manner the time complexity is too high, the following describes the time complexity is O (n) algorithm to Manacher.

Two, Manacher algorithm based on the concept

1, the radius of the array radius palindrome

Palindrome radius array palindromic radius is used to record length of the radius of each character position of the center palindromic obtained, as shown below, referring to the position p1 radius [. 6] palindrome radius 5, each an array of radial positions palindrome is a palindrome consisting array, so palindromic radius array # a # c # b # b # c # b # d # s # is [1, 2, 1, 2, 1, 2 , 5, 2, 1, 4, 1, 2, 1, 2, 1, 2, 1].

 

2, the right border of the rightmost R palindrome

A position right border of the rightmost palindrome palindrome refers to the sub-location and location prior to this series, the rightmost place of arrival. For example, a string # a # c # b # b # c # b # d # s #, each seeking its position as follows:

 

Rightmost palindrome right boundary of R process

 

The very beginning R = -1, the p = 0 position, that is its own palindrome, the palindrome rightmost right boundary R = 0; when p = 1, there is a palindromic sequence # a #, R = 2; p = 2, R = 2; P = the time 3, R = 6; when p = 4, the right border of the rightmost palindromic or right margin of p = 3, R = 6, and so on.

3, the right border of the rightmost palindromic symmetry center C

Right border is rightmost palindromic above-mentioned center point C, as shown below, when p = 4, R = 6, C = 3

 
Rightmost palindrome right border of the center C

Third, the process Manacher algorithm

First major aspects divided into two cases:

The first case: the next position to be moved to the right of the rightmost right border R of the palindrome.

For example, in the beginning, R = -1, p, next to a moved position p = 0, p = 0 at R = -1 on the right; = 0, R = 0 at this time, the p-p at a shift position is p = 1, also R = 0 on the right.

In this case, a common solution, the moved position of the center of symmetry, spread to both sides, while the update array radius palindrome, the palindrome center of symmetry of the rightmost and rightmost right border R palindromic right boundary C.

The second case: move to the next position is the most right-palindrome right boundary of R or R on the left

In this case it is divided into three types:

1, to move to the next position p1 is not the rightmost palindromic right boundary the right R, and cL <pL.

C p1 to p2 is the center of symmetry point of symmetry;

pL is the center of symmetry of p2 palindromic substring left border;

cL is the center of symmetry C of the left border palindromic substring.

P1 palindromic radius in this case is the palindromic radius p2 radius [p2].

 
p1<=R且cL<pL

2, moved to the next position p1 ticket is not the rightmost palindromic right of the right boundary of R, and cL> pL.

C p1 to p2 is the center of symmetry point of symmetry;

pL is the center of symmetry of p2 palindromic substring left border;

cL is the center of symmetry C of the left border palindromic substring.

Palindrome radius p1 p1 is in this case to the distance R R-p1 + 1.

 
p1<=R且cL>pL

3, next to a moved position p1 ticket is not the rightmost palindromic right of the right boundary of R, and cL = pL;

C p1 to p2 is the center of symmetry point of symmetry;

pL is the center of symmetry of p2 palindromic substring left border;

cL is the center of symmetry C of the left border palindromic substring.

Palindrome radius R and C. update on p1 will continue to expand out of this situation, but then just out from R to expand it, expand after

 
p1 <= R and cL == pL

Four, Manacher time complexity analysis

From the above analysis, it can be seen, the time required for a location palindromic radius of the second case 2 is a complexity of O (1), the first case and the second case 3, when R is a constantly expanding outwardly, will not retreat back and find palindromic radius R of the position is not within the judgment, and so the entire string, R is moved from a moving start point string to the end, the time complexity is O (n), so the whole time complexity is manacher O (n).

Five, Manacher of code implementation

#include<iostream>
#include<vector>
using namespace std;

int Manacher(string str){
    int str_len = str.size();
    vector<char> tmp;
    tmp.push_back('$');
    int len[2*str_len];
    for(int i = 1;i < str_len;i++){
        tmp.push_back('#');
        tmp.push_back(str[i]);
    }
    tmp.push_back('#');
    for(char i : tmp)
        cout << i;
    cout << endl;
    int mx = 0;
    int max_len = -1;
    int mid = 0, pos = 0;
    for(int i = 1; tmp[i]; i++)
    {
        if(i < mx)
            len[i] = min(len[2*mid-i],mx-i);
        else
            len[i] = 1;

        while(tmp[i-len[i]] == tmp[i+len[i]])
            len[i]++;

        if(len[i]+i > mx){
            mx = len[i]+i;
            mid = i;
        }
        if(max_len <= len[i]-1)
        {
            max_len = len[i]-1;
            pos = i;
        }
       // maxlen = max(maxlen,len[i]-1);
    }
    for(int i=pos-max_len; i<pos+max_len; ++i) {
        if (tmp[i] != '#')
            cout << tmp[i];
    }
    cout << endl;
    return max_len;
}
int main(){
    string str;
    cin >> str;
    cout << Manacher(str);
    return 0;
}

Guess you like

Origin www.cnblogs.com/jodio/p/11441200.html