Detailed explanation and template of Manacher algorithm

Detailed Algorithm

The Manacher algorithm can solve the longest palindrome substring in linear time. It can be said that the implementation is very clever. His basic idea is that the extension of the palindrome substring from the middle to both sides must be the same, so first we need to perform certain operations on the string. Preprocessing:

For example: String: aaaa aba

Then their lengths are even and odd respectively, because if it is even, we can't find a midpoint to make both sides the same, so we add a non-appearing character between every two characters to make them all odd :

#a#a#a#a# #a#b#a# This will definitely find the midpoint of a longest palindrome

We let p[i] , which means that the point i is the center, can be extended to the rightmost length, maxlen means: the farthest distance that can be extended (traversing all points, the longest distance that can be extended)

Now we have to traverse the string from the beginning to calculate p[i], and use p[i] to continuously update maxlen, so because we added '#', our final answer is maxlen-1

Suppose that our current traversal position is k+i, and i in all points before k is the farthest distance extended, that is, maxlen = p[i]

The latter situation is divided into two types:

1) When k+i > maxlen, we cannot find a point corresponding to this point, then initialize p[k+i] = 1, and then traverse from this point to both sides to find the longest palindrome string:

while(s[k + p[k+i]] == s[k - s[k+i]) p[k+i]++;

2) When k+i < maxlen

①When the left end of the palindrome and the corresponding point ik is greater than the left end of i


In this case, the length of our p[i+k] must be the length from i+k to the right endpoint of i, that is: p[i+k] = p[i] - k, because if it is longer, then the length of i The length must be more than the current length, it can still be extended to the right

②When the left end of the palindrome and the corresponding point ik is greater than the left end of i


Then p[i+k] = p[ik]

When the left end of the palindrome and the corresponding point ik is equal to the left end of i


At this time, p[i+k] must be greater than or equal to p[ik], and then we need to continue to judge while(s[i+k+p[i+k]] == s[i+k - p[ik]] ) p[i+k] ++;

We can conclude that:

p [i + k] = min (p [i] - k, p [i - k]);
while(s[i+k+p[i+k]] == s[i+k - p[i-k]] ) p[i+k] ++;

Then traversing to the end of the string can solve the final answer

Chestnuts & Templates

HDU 3068

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
const int N = 110000 + 10;
intmain()
{
    char s[N*2];
    int p[N*2];
    while(~scanf("%s",s))
    {
        int len ​​= strlen(s);
        for(int i = len;i >= 0;i --)
        {
            s[i+i+2] = s[i];
            s[i+i+1] = '#';
        }
        s[0] = '*';
        int maxlen = 0,id = 0;
        for(int i = 2;i < len*2+1 ;i ++)
        {
            if(p[id]+id > i) p[i] = min(p[id*2-i] , p[id] + id - i);
            else p[i] = 1;
            while(s[i + p[i]] == s[i - p[i]]) p[i] ++;
            if(p[id]+id < p[i]+i) id = i;
            if(maxlen < p[i]) maxlen = p[i];
        }
        printf("%d\n",maxlen-1);
    }
    return 0;
}

Reference blog

https://blog.csdn.net/xingyeyongheng/article/details/9310555

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326521142&siteId=291194637