Algorithm Advanced Manacher algorithm (longest palindrome)

Source: Internet
Author: User

A few days ago Bestcode to do a string of topics, need O (n) palindrome, just see the online manacher algorithm, so to learn a


Go to the Chase:

Manacher algorithm


Usage: Generally used to find the largest palindrome of a string, the operation will be recorded at each point as the center of the palindrome radius, can be used for other operations

Time complexity: O (N)

Spatial complexity: Record string 2*n, radius array 2*n


Content:

Kee P[i] for the center of the palindrome radius (the ABA in the center of the B-centered palindrome radius of 2, then if it is an even number of palindrome, such as ABBA? Here we discuss the odd number, even after the number, the simple is to use the character fill to become odd.

So the following sections are all discussed in the odd number of palindrome >>>>>>>>>>>>>>

Then there is no way to avoid the first for once, for (j=0;j<n;i++) to ask for each p[j], the following is the solution to P[j] (j=i+k)

Analysis: Suppose the i+k has been calculated front of the 0~i+k-1 p, now requires p[i+k],

So first, according to the front of the point to find the radius when there is no traverse to the i+k this point can be divided into two major categories:

First, the point in the front of the radius of the time has not traversed to i+k this point, that is, p[i]+i<i+k

(Set I to the front i+k points in the radius when the closest to the point near the string, not the longest palindrome!) )

So at this time p[i+k]=1;

At this time the i+k has not looked for the radius, need to start from scratch to find while (S[i+k+p[i+k]]==s[i+k-p[i+k]]) p[i+k]++;

Second, The previous point radius has been traversed to the point of I+k, that is, p[i]+i>=i+k
(Set I to the front i+k points in the radius when the closest to the point near the string, not the longest palindrome!) )

At this time i+k in front of the I symmetric i-k, so calculate i+k palindrome radius do not need to start from the first to find, then is from p[i-k] start looking?

The answer is not necessarily!

The following is a picture of the Internet to analyze the possible two situations:


<1>p[i]-k<p[i-k] (at this time P[i-k]>=p[i+k]), the following is a combination of image analysis


First of all, the red line in the figure is the palindrome radius of I, the black line is I seek palindrome radius traversed by the point, dark blue is the i-k of the palindrome radius, then i+k the palindrome radius must be Orange line, why?

First the Orange Line portion must be part of the radius of the i+k, as symmetry can be obtained with the Orange Line portion of the left I-k,

So the radius of the i+k may be greater than the Orange Line part?

Assuming that the i+k of the palindrome radius is greater than the Orange Line, such as the Orange Line + Purple Line, then because the symmetry i-k also must contain the Purple Line part, then P[i] is no longer the original p[i], but as the black line + purple lines, this with the previous contradiction, so it is impossible to exist


namely P[i+k]=p[i]-k;

<2>P[i]-k>=p[i-k] (at this time P[i-k]<=p[i+k]), the following is a combination of image analysis


The red line in the figure is the palindrome radius of I, the black line for I seek palindrome radius traversed by the point, dark blue is the i-k of the palindrome radius, first of all, because of the symmetry i+k the palindrome radius must contain the Blue line part, at the same time i+k the right side may also have the word RP composition longer palindrome, the final formation of the Orange Line +k]>=p[i-k], so you can assign a value of p[i+k]=p[i-k], then while (S[i+k+p[i+k]]==s[i+k-p[i+k]) p[i+k]++; Keep looking back.


So from the above can be summed up P[j] The method of seeking:

void query_p (int n)                             //n is the length of the string {    int id = 0;                                 ID for the above i    p[0] = 1;    for (int j=1;j<n;j++)                        //j is the above i+k, so K=j-id    {                       if (p[id]+id<=j) p[j]=1;                 First case        Else P[j]=min (p[2*id-j],p[id]-(J-id));  Two small cases of the second case        while (S[j+p[j]]==s[j-p[j]]) p[j]++;     Continue looking for        if (p[j]+j>p[id]+id) id=j;               Update closest to the point following the string    }}

<<<<<<<<<<<<<<<<<<<<<<<<<<< <<<<<<< so far here are the palindrome as an odd number to calculate, then if there is an even number of how to do it, the specific method is to use the character fill, the character can be used in the string will not appear in the characters to fill, the specific method is:

Assuming that there are only letters in a string, you can fill it with a special symbol by inserting the same character in front of each character

For example, when filling a character #, the original string is Abba, the filled character becomes #a#b#b#a#, and then it is possible, as for the original palindrome radius of the letter is now p[i]/2+1, the fill character will not affect the result.

However, it is important to note that in order to avoid the array out-of-bounds need to be processed after the character in the characters, such as the above * #a #b#b#a# ' ", so that the first letter from the beginning of the traversal of the problem will not occur

Here is a post-populated code for the longest palindrome:

int For_max (int n)                             //n is the length of the original string {for    (int j=n;j>=0;j--)                       //character padding    {        s[j*2+2]=s[j];        s[j*2+1]= ' # ';    }    S[0]= ' $ ';                                   Prevents the array from being filled out of bounds with the first character and the last character as ' $ ' and '/0 '    int id = 0;                                 ID for the above i    int maxlen = 0;    P[0] = 1;    for (int j=2;j<2*n+2;j++)                        //j is the above i+k, so K=j-id    {        if (p[id]+id<=j) p[j]=1;                 First case        Else P[j]=min (p[2*id-j],p[id]-(J-id));  Two small cases of the second case        while (S[j+p[j]]==s[j-p[j]]) p[j]++;     Continue looking for        if (p[j]+j>p[id]+id) id=j;               Update the point Maxlen=max nearest to the string        (maxlen,p[j]-1);              Update Longest palindrome    }    return maxlen;}



Specific topics can be seen HDU3068: Test instructions about to give a string, to find the longest return is how much

http://acm.hdu.edu.cn/showproblem.php?pid=3068

The code is as follows:

#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include < algorithm> #include <vector> #pragma comment (linker, "/stack:1024000000,1024000000") using namespace std;                         const int MAXN = 2.2E5+5;                                 Char s[maxn*2];                       Twice times array int p[maxn*2];int For_max (int n)//n is the length of the original string {for (int j=n;j>=0;j--)        Character padding {s[j*2+2]=s[j];    s[j*2+1]= ' # ';                                   } s[0]= ' $ ';                                 Prevents the array from being filled out of bounds with the first character and the last character as ' $ ' and '/0 ' int id = 0;    ID for the above i int maxlen = 0;    P[0] = 1;                 for (int j=2;j<2*n+2;j++)//j is the above i+k, so K=j-id {if (p[id]+id<=j) p[j]=1;  First Case Else P[j]=min (p[2*id-j],p[id]-(J-id));     Two small cases of the second case while (S[j+p[j]]==s[j-p[j]]) p[j]++;               Continue looking for if (p[j]+j>p[id]+id) id=j; Update the point closest to the string following the MaxleN=max (maxlen,p[j]-1); Update Longest palindrome} return maxlen;}    int main () {int n;        while (scanf ("%s", s)!=eof) {int M=strlen (s);    printf ("%d\n", For_max (m)); }}




Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Algorithm Advanced Manacher algorithm (longest palindrome)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.