Manacher (horse-drawn cart) algorithm & template

Introduction

Manacher algorithm can solve some palindrome problems within O(n) complexity, such as finding the longest palindrome substring.
The algorithm was invented by Manacher.

Ideas

Manacher preprocessing part

First of all, for a character string, its reply string can be divided into even-length and odd-length palindrome substrings according to the length. The symmetry centers of the two palindrome strings are different, which may cause trouble in processing.
Therefore, the string must be processed to unify the odd and even substrings.
such as:

ababa

Manaher's approach is to insert some irrelevant characters (such as #)

#a#b#a#b#a#

The advantage of this is obvious. For even-numbered substrings, its symmetry center will become #, so that the symmetry centers corresponding to all substrings in the original string can be found in the processed string.

In addition, another extraneous character (such as $) needs to be added at the beginning

$#a#b#a#b#a#

Then the preprocessing part is done at this time

The core part of Manacher

The final result of Manacher is to get such an array p, P[i] represents the maximum length of the palindrome centered on i that can extend to the right. For
example:

$#a#b#a#b#a#(Subscript starts from 1)
p[2] = 1(#), p[3] = 2(a#), p[5] = 4(b#a#)

Before getting the p array, two auxiliary variables idx and maxx are required to indicate the range of the nearest text string. For
example,
Insert picture description here
maxx = idx + p[idx] can be obtained.

Assuming that a segment of p has been processed, if the current position of p is required to be within the range of maxx, there will be the following relationship.
p [i] = min (p [idx ∗ 2 − ​​i], maxx − i) p[i] = min(p[idx * 2-i], maxx-i)p[i]=min(p[idx2i],maxxi )
Insert picture description here
First, if it is within maxx, a symmetrici ′i'can be foundi Then p[i'] has been calculated. Because of the symmetry relationship, part of the p of i'is also i. You can quickly findi ′ = idx ∗ 2 − ​​ii' = idx * 2-ii=idx2i
but ifp [i ′] p[i']p[i ] Isvery large, beyond the range of maxx, then the excess part cannot be guaranteed at this timeiii is symmetric, so you need to set an upper boundmaxx − i maxx-imaxxi , completion of acquisitionp [i] = min (p [idx ∗ 2 − ​​i], maxx − i) p [i] = min (p [idx * 2 --i], maxx --i)p[i]=min(p[idx2i],maxxi)

If i itself is not in the maxx range, then direct brute force matching is fine.

Code

char str[maxn], s[maxn];
int len1, len2, p[maxn];

void Manacher(){
    
    
    str[1] = '$', str[2] = '#';
    len2 = strlen(s + 1);
    for(int i = 1; i <= len2; i++){
    
    
        str[i * 2 + 1] = s[i];
        str[i * 2 + 2] = '#';
    }
    len1 = len2 * 2 + 2;

    int idx = 0, maxx = 0;
    for(int i = 2; i <= len1; i++){
    
    
        if(maxx > i)p[i] = min(p[idx * 2 - i], maxx - i);//核心代码
        else p[i] = 1;
        for(; str[i + p[i]] == str[i - p[i]]; p[i]++);//暴力向后匹配
        if(p[i] + i > maxx)idx = i, maxx = p[i] + i;//更新maxx和idx
    }
}

The final value of p minus one is the length of the longest palindrome at the center.

Guess you like

Origin blog.csdn.net/qq_36102055/article/details/108933268