Manacher calculates palindrome substring

Manacher algorithm

The title description gives a string SS consisting of only lowercase English characters. Find the length of the longest palindrome string in SS.
The length of the string is
a string SS composed of a line of lowercase English characters a, b, c,...y, z in the input format of nn .

The output format is an integer representing the answer.

Input and output sample input #1 aaa
output #1 3

The traditional idea of ​​finding the longest palindrome substring is to traverse each character, and search for it on both sides with the character as the center. The time complexity is O(n2), and the efficiency is very low. In 1975, a person named Manacher invented an algorithm, the Manacher algorithm (commonly known as the horse-drawn cart algorithm), which can improve the efficiency of the algorithm to O(n).

First of all, because the sequence is divided into odd sequence and even sequence, in order to avoid discussion, I think it will be converted into odd sequence. The specific method is: insert a character at the beginning and end of the string and between each character (the inserted character is not in the original string).

eg1

   插入的是同样的符号,且符号不存在于原串,因此子串的回文性不受影响。
   原来是回文的串,插完之后还是回文的,
   原来不是回文的,依然不会是回文。调整后,串的长度都转换成了奇数。

We call the distance between the leftmost or rightmost character in a palindrome string and its symmetry axis as the palindrome radius. Manacher defines a palindrome radius array R, using R[i] to represent the palindrome radius of the palindrome string with the i-th character as the axis of symmetry.
Insert picture description here
It can be seen that R[i]-1 is exactly the length of the longest palindrome centered on i in the original string.
The longest palindrome string length of the original string is max{ R[i]-1 },
so the question becomes, how to find the R array efficiently.
**

The basic idea is to use the symmetry of the palindrome to extend the palindrome.

**
We discuss the length of the palindrome radius centered on each character from left to right. Let MaxLen represent the position that can be reached on the far right of the palindrome substrings discussed so far, and use P to record the center position of the corresponding palindrome substring.
Insert picture description here
Red represents R[i] corresponding to p, and black represents p.
We find the R[] of each character in turn from left to right, assuming that the currently visited position is i, that is, R[i] is required. In the corresponding figure, i must be on the right of P. But we are more concerned about whether i is on the left or right of MaxLen. We need to discuss it separately.

i<maxlen

Insert picture description here
Due to symmetry, we can deduce that R[i] is not less than the corresponding point R[2 p-i] about p (**if i +r[2 pi]<maxlen**), but it is also possible that R[ 2*pi] is very large, at this time R[i] can only get maxlen-i+1;

i>maxlen

At this time, it is obvious that R[i]=1; in the
last step, we have to update maxlen and the corresponding p value.
**The code is as follows **

#include<bits/stdc++.h>
using namespace std;
char ss[100009];
char ch[200009];
int r[500009];
int inti()
{
    
    
	int len=strlen(ss);
	int j=0;
	ch[0]='@';
	ch[1]='#';
	j=2;
	for(int i=0;i<len;i++)
	{
    
    
		ch[j++]=ss[i];
		ch[j++]='#';
	}
	ch[j]='\0';
//	for(int i=1;i<=j;i++)
//		putchar(ch[i]);
//	cout<<endl;
	return j;
}
int manachar()
{
    
    
	int len=inti();
	int p=0,maxlen=0;

	for(int i=1;i<=400000;i++)
		r[i]=0;

	for(int i=1;i<len;i++)
	{
    
    
		if(i<maxlen)r[i]=min(r[2*p-i],maxlen-i+1);
		else r[i]=1;//最重要的优化
		while(ch[i-r[i]]==ch[i+r[i]])r[i]++;//更新R[i]
		if(maxlen<i+r[i]-1)//更新相应的maxlen和p
		{
    
    
			maxlen=i+r[i]-1;
			p=i;
		}
	}
	return len;
}

Guess you like

Origin blog.csdn.net/m0_50089378/article/details/109294188