manacher算法——回文串计算的高效算法
manacher算法的由来不再赘述,自行百度QWQ。。。
进入正题,manacher算法是一个高效的计算回文串的算法,回文串如果不知道可以给出一个例子:“ noon ”,这样应该就很清晰了;
其实这个算法虽然名字长,但是实际代码很短,而且理解起来并不难。。。(连我这种蒟蒻都懂了)
这里给出模板题
题目描述
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
字符串长度为n
输入格式
一行小写英文字符a,b,c...y,z组成的字符串S
输出格式
一个整数表示答案
其中n的范围为11000000,很显然,只能是O(n)的复杂度,但是为何复杂度这么优秀,这里在讲完算法之后会简述。
定理:
- 一个回文串只有一个对称中心,这个中心上可能有字母或者没有(如果没有字母,我们可以再加上一个,再后面会解释),我们暂且定义其为mid;
- mid两端的区间对称,两边全等(回文串的定义);
- 如果一个大的回文串一端的区间中有回文串,我们先定义它的中心为 i ,那么大回文串的另一端一定会有相同的回文串;
- 根据上一条,如果我们要更新在右端区间的回文串,那么在左边的回文串半径就可以更新右边的,但是有大回文串的区间限制,所以应当两者取min;
- 结束上面定理的继承之后,直接暴力枚举检查是否两端更新。
解释:
上面的原理毕竟太过干,只是纯理论,所以制图说明;

比如说这个区间是一个大回文串,我们我们用r保留其有边界,那么l就可以根据中点坐标公式变形得到mid*2 - r,所以我们只保留右边界 r 即可。
那么可以看见,如果我们以 i 为这段区间中一个回文串的中心,那么,与它对称的回文串中心就可以求出(根据中点公式,得2*mid - i ,与上面相同);
那么我们就可以根据定理来继承左边回文串的半径,但是如果左边这个回文串有超过区间的部分怎么办?
这里就用到我们所说的取min了,将左边回文串半径和r - i相比取min,这里就得到了 i 的一个半径,但这个半径一定小于或等于真实半径,所以还需暴力枚举;
这里就可见manachar算法的核心操作了,就是枚举回文串中心,然后继承半径以来减少枚举的次数;
我们用p[ i ]表示以点 i 为中心的回文串的半径,r记录回文串到达的最右边的坐标,mid随之更新,记录这个回文串的中心;
Code
#include<bits/stdc++.h>
#define maxn 22000007
using namespace std;
char dat[maxn];
int p[maxn],r,cnt=1,mid,ans; void scan(){
char s=getchar();
dat[0]='~';//为了不超出边界的小操作
dat[1]='|';//这个间隔解决了对称中心没有字母的情况
while(s>='a'&&s<='z'){
dat[++cnt]=s;
dat[++cnt]='|';
s=getchar();
}//其实与读入优化没差啦
}//自定义读入 int main(){
scan();
for(int i=2;i<=cnt;i++){
if(r>i) p[i]=min(p[2*mid-i],r-i);//由对称的回文串继承,用r-i限制
else p[i]=1;//CASE :无法继承
while(dat[i-p[i]]==dat[i+p[i]]) p[i]++;//暴力更新
if(p[i]+i>r) r=p[i]+i,mid=i;// r边界必须是最右
ans=max(ans,p[i]);//更新答案
}
printf("%d\n",ans-1);//这个减一可以自己模拟一下,数学推了话好麻烦的说
}
这就是manachar算法的简述了,当然这里解释一下为什么复杂度为O(n):
我感觉这和KMP复杂度有些类似,因为这里因为继承的缘故,所以每个点更新次数较少,然后均摊到每个循环,那么复杂度就变成了O(n)了;
manacher算法——回文串计算的高效算法的更多相关文章
- Girls' research - HDU 3294 (Manacher处理回文串)
题目大意:给以一个字符串,求出来这个字符串的最长回文串,不过这个字符串不是原串,而是转换过的,转换的原则就是先给一个字符 例如 'b' 意思就是字符把字符b转换成字符 a,那么c->b, d-& ...
- leetcode:Palindrome Number (判断数字是否回文串) 【面试算法题】
题目: Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could neg ...
- hdu 3294 manacher 求回文串
感谢: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ O(n)求给定字符串的以每个位置为中心的回文串长度. 中心思想:每次计算位 ...
- HDU 5340——Three Palindromes——————【manacher处理回文串】
Three Palindromes Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- HDU 5371 Hotaru's problem (Manacher,回文串)
题意:给一个序列,找出1个连续子序列,将其平分成前,中,后等长的3段子序列,要求[前]和[中]是回文,[中]和[后]是回文.求3段最长为多少?由于平分的关系,所以答案应该是3的倍数. 思路:先Mana ...
- 算法 -- 四种方法获取的最长“回文串”,并对时间复杂进行分析对比&PHP
https://blog.csdn.net/hongyuancao/article/details/82962382 “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就 ...
- 2015 UESTC Training for Search Algorithm & String - M - Palindromic String【Manacher回文串】
O(n)的复杂度求回文串:Manacher算法 定义一个回文值,字符串S是K重回文串,当且仅当S是回文串,且其长度为⌊N/2⌋的前缀和长度为⌊N/2⌋的后缀是K−1重回文串 现在给一个2*10^6长度 ...
- 最长回文子串问题 O(n)算法 manacher URAL1297 HDU3068
先来看一道简单的题,ural1297 给定一个1000长度的字符串,求最长回文子串. 看起来很Naive,乱搞一下,O(n^2)都可以解决. 再来看这个题 HDU3068 120个110000长度的字 ...
- 马拉车,O(n)求回文串
马拉车,O(n)求回文串 对整个马拉车算法步骤做个总结: 第一步:将每个原字母用两个特殊字符包围如: aaa --> #a#a#a# abab -->#a#b#a#b 同时可以由这个翻倍的 ...
随机推荐
- 使用Python自动填写问卷星(pyppeteer反爬虫版)
写此文的目的是为了方便寒假自己忘记填问卷星 一开始的想法和去年一样,去年就写过一版,想着今年不过就是改改数据,换换id而已,另外没想到的事情发生了... 满怀信心的写完代码 from selenium ...
- 面试官:你真的了解Redis分布式锁吗?
什么是分布式锁 说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程.性能高的特点,它还经常被用于做分布式锁. 锁我们都知道,在程序中的作用就是同步工具,保证共享资源在同 ...
- 【JDBC核心】实现 CRUD 操作
实现 CRUD 操作 操作和访问数据库 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果.其实一个数据库连接就是一个 Socket 连接. java.sql 包中有 ...
- 经常使用的Sublime Text 快捷键
最常用的 Sublime快捷键:
- zabbix 监控tomcat
zabbix 监控tomcat server端rpm -ivh jdk-8u20-linux-x64.rpmvi /etc/profileJAVA_HOME=/usr/java/jdk1.8.0_20 ...
- mysql: Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/share/mysql/charsets/Index.xml' file
mysql: Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/sha ...
- MoChat - 国内首款完全开源的 PHP 企业微信管理系统正式发布
MoChat -- 让企业微信开发更简单 项目地址 Github: https://github.com/mochat-cloud/mochat Gitee: https://gitee.com/mo ...
- 透过现象看本质:Java类动态加载和热替换
摘要:本文主要介绍类加载器.自定义类加载器及类的加载和卸载等内容,并举例介绍了Java类的热替换. 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次 ...
- ORA-00054: 資源正被使用中, 請設定 NOWAIT 來取得它, 否則逾時到期
1.查看被使用资源的OBJECT_ID SELECT *FROM DBA_OBJECTS WHERE OBJECT_NAME='OBJECT_NAME' 2.查看资源被谁占用SELECT * FROM ...
- Promise.all()使用实例
一.什么是Promise.all()? 在说这个之前要先说清楚promise.promise就是一个对象,专门用来处理异步操作的. 而Promise.all方法用于将多个 Promise 实例,包装成 ...