Palindrome string algorithm Manacher

Palindrome string algorithm Manacher

First, in a very clever way, all possible palindrome substrings of odd / even length are converted to odd length: a special symbol is inserted on both sides of each character. For example, abba becomes a, B, a, and aba becomes a, B, and a. In order to further reduce the complexity of encoding, you can add another special character at the beginning of the string, so that you don't need to deal with cross-border problems, such as $ාaාbාaා.

Take the string 12212321 as an example. After the previous step, it becomes S [] = "$ා񖓿1 × 2 × 2 × 2 × 1 × 2 × 3 × 2 × 1 × 1 × 3 × 3 × 2 × 2 × 1 × 3";

Then an array P[i] is used to record the length of left / right extension (including S[i]) of the longest palindrome substring centered on the character S[i], such as the corresponding relationship between S and P

S # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
(p.s. As you can see, P[i]-1 Exactly the total length of palindrome string in the original string)

Next, calculate P[i]. This algorithm adds two auxiliary variables ID and mx, where id represents the position of the center of the largest palindrome substring, and mx is id+P[id], that is, the boundary of the largest palindrome substring.

Here is the key point of this algorithm:

Mp[i] = mx > i ? min(Mp[2*id-i],mx-i):1;

In fact, it is the problem of symmetry point and boundary.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000010;

char Ma[maxn*2];
int Mp[maxn*2];
char s[maxn];

void Manacher(char s[],int len)
{
    int l = 0;
    Ma[l++] = '$';
    Ma[l++] = '#';
    for(int i = 0;i < len; i++) {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = 0;
    int mx = 0,id = 0;
    for(int i = 0;i < l; i++) {
        Mp[i] = mx > i ? min(Mp[2*id-i],mx-i):1;
        while(Ma[i+Mp[i]] == Ma[i-Mp[i]]) Mp[i]++;
        if(i + Mp[i] > mx) {
            mx = i + Mp[i];
            id = i;
        }
    }
}
int main()
{
    freopen("in.txt","r",stdin);
    int ncase = 1;
    while(scanf("%s",s) == 1) {
        if(strcmp(s,"END") == 0) break;
        int len = strlen(s);
        Manacher(s,len);
        int ans = 0;
        for(int i = 0;i < 2*len+2; i++)
            ans = max(ans,Mp[i]-1);
        printf("Case %d: %d\n",ncase++,ans);
    }

    return 0;
}

Tags: encoding

Posted on Tue, 05 May 2020 08:07:15 -0400 by johnoc