[模板] Manacher(马拉车)算法

用途

求回文子串

做法

先考虑回文子串以某字符为中心的情况,即长度为奇数

推着做,记rad[i]为以i位置为中心的最大半径(包含中点)

考虑怎么求rad[i]。找之前的一个右端点最靠右的位置p,设它的中心是j

如果有i<p,那么找到i关于j的对称点2*j-i,那么一定$rad[i]>=min\{rad[2*j-i],[p-i+1]\}$

如果i>=p,那前面做的东西对我求i没什么帮助,rad[i]>=1

然后再暴力往后判断rad[i]能不能再大一点

因为这个右端点最靠右的位置一定是递增的,所以能感受出这是一个O(n)的算法

 

为了解决串长为偶数的问题,我们在每两个字符间(以及开头结尾?)都插个相同的特殊符号;为了避免可能的溢出,在最开始再插个别的符号

例题

 1 #include<bits/stdc++.h>
 2 #define CLR(a,x) memset(a,x,sizeof(a))
 3 using namespace std;
 4 typedef long long ll;
 5 typedef pair<int,int> pa;
 6 const int maxn=2.2e7+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 char s[maxn];
16 int r[maxn];
17 
18 int main(){
19     //freopen("","r",stdin);
20     int i,j,k;
21     scanf("%s",s+1);s[0]='!';
22     int len=strlen(s+1);
23     for(i=len;i>=0;i--){
24         s[i<<1]=s[i],s[i<<1|1]='#';
25     }len=len*2+1;
26     int mp=0,mi=0,ans=0;
27     for(i=1;i<=len;i++){
28         r[i]=i<=mp?min(mp-i+1,r[mi*2-i]):1;
29         while(s[i+r[i]]==s[i-r[i]]) r[i]++;
30         if(i+r[i]-1>mp) mp=i+r[i]-1,mi=i;
31         ans=max(ans,r[i]);
32     }printf("%d\n",ans-1);
33     return 0;
34 }

 

转载于:https://www.cnblogs.com/Ressed/p/9957413.html

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值