【知识点】manacher算法匹配回文字符串

模板题

洛谷P3805 【模板】manacher

给出一个只由小写英文字符 \(\texttt a,\texttt b,\texttt c,\ldots\texttt y,\texttt z\) 组成的字符串 \(S\) ,求 \(S\) 中最长回文串的长度 。

字符串长度为 \(n\)

输入格式

一行小写英文字符 \(\texttt a,\texttt b,\texttt c,\cdots,\texttt y,\texttt z\) 组成的字符串 \(S\)

输出格式

一个整数表示答案。

输入输出样例 #1

输入 #1

aaa

输出 #1

3

说明/提示

\(1\le n\le 1.1\times 10^7\)

Manacher

Manacher算法(又称马拉车算法)是一种用于在线性时间复杂度(O(n))内求解字符串最长回文子串的高效算法。其核心思想是通过预处理统一奇偶回文,并利用对称性避免重复计算。
对于偶数长度的字符串,插入无关符号作为预处理,以保证长度为奇数。需要s[0]为不相干的符号,防止越界。
若已知以id为中心的回文串右边界为mx,则对于i < mx的位置,其回文半径可基于对称点j=2*id-i快速初始化:
Len[j] < mx-iLen[i] = Len[j]
否则 → Len[i] = mx-i,再向外扩展更新边界。
时间复杂度为O(n),非常好用!!!

模板题题解

AC代码

AC代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;

const i64 MAXN = 2.5e7+5;
i64 ans = 0,len = 2,r[MAXN],mid,mr;
char c[MAXN],ch;

int main(){
	//预处理+输入
	c[0] = '~';
	c[1] = '#';
	while(1){
		ch = getchar();
		if(ch == ' ' || ch == '\n' || ch == EOF)	break;
		
		c[len++] = ch;
		c[len++] = '#';
	}
	c[len++] = '!';
	
	//Manacher算法
	for(i64 i = 2;i<len;i++){
		//初始化回文半径
		if(i <= mr) 	r[i] = min(r[mid * 2 - i], mr - i);
		else 			r[i] = 0;
		//中心扩展
		while(i - r[i] - 1 >= 0 && i + r[i] + 1 < len &&c[i - r[i] - 1] == c[i + r[i] + 1]) 	r[i]++;
		//更新最右边界
		if(i + r[i] > mr){
			mr = i + r[i];
			mid = i;
		} 
		//更新答案
		ans = max(ans, r[i]);
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2025-03-11 22:11  Alkaid16  阅读(17)  评论(0)    收藏  举报