模板:manacher算法

本文深入讲解了Manacher算法,一种高效查找字符串中最长回文子串的方法。通过在字符串间插入特殊字符,利用回文串的对称性质,优化搜索过程。文章详细解释了算法流程,包括关键变量maxright和mid的作用,以及如何通过动态更新实现快速计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.luogu.org/problemnew/show/P3805

回文串长度的奇偶性造成了对称轴的位置可能在某字符上,也可能在两个字符之间的空隙处

那么manacher对此的优化是在每两个字符中间插入另一个字符,如'#'。

用一个辅助数组r表示每个点能够扩展出的回文长度

我们先设置一个辅助变量maxright,表示已经触及到的最右边的字符

另外还要设置一个辅助变量mid,表示包含maxright的回文串的对称轴所在的位置

当i在maxright左边且在mid右边时:

设i关于mid的对称点为j,显然r[i]一定不会小于r[j]。(对称)

我们没必要保存j,j可以通过计算得出,为:(mid<<1)−i

那么我们就设置r[i]=r[j]然后继续尝试扩展,这样就可以较快地求出r[i],然后更新maxright和mid

当i在maxright右边时,我们无法得知关于r[i]的信息,只好从1开始遍历,然后更新maxright和mid

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 char t[11000010], a[11000010];
 6 int n, m, ans=0;
 7 int r[23000000];
 8 int main() {
 9     scanf("%s", t);
10     m=strlen(t);
11     a[0]=a[1]='#';
12     for(int i=1; i<=m; i++){
13         a[(i<<1)]=t[i-1];
14         a[(i<<1)+1]='#';
15     }
16     n=(m<<1)+2;
17     int mid=1, maxright=1;
18     r[1]=1;
19     for(int i=2; i<n; i++){
20         if(i<maxright) r[i]=min(r[(mid<<1)-i], r[mid]+mid-i); 
21         else  r[i]=1;
22         while(a[i-r[i]]==a[i+r[i]]) r[i]++;
23         if(i+r[i]>maxright){
24             maxright=i+r[i];
25             mid=i;
26         }
27         if(r[i]>ans)    ans=r[i];
28     }
29     printf("%d\n", ans-1);
30     return 0;
31 }

 

转载于:https://www.cnblogs.com/Aze-qwq/p/9891115.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值