【知识点】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-i → Len[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;
}

浙公网安备 33010602011771号