Manacher(马拉车)
Manacher
一 、背景
1975年,Manacher发明了Manacher算法(中文名:马拉车算法),是一个可以在O(n)的复杂度中返回字符串s中最长回文子串长度的算法,十分巧妙。
让我们举个例子:
1.字符串:abbababa 最长回文子串:5(abbababa)
2.字符串:abcbbabbc 最长回文子串:7(abcbbabbc)
3.字符串:abccbaba 最长回文子串:6(abccbaba)
传统方法是,遍历每个字符,以该字符为中心向两边查找。时间复杂度为O(n^2),效率很差;
但是Manacher算法的时间复杂度可以达到O(n)!
下面让我们看看它是怎么做的的吧
二、算法过程分析
回文分为奇回文(ababa)和偶回文(abba),这里比较难以处理,我们使用一个骚操作(划重点)。
我们将字符串首尾和每个字符间插入一个字符(注意:这个自符在串中并未出现)例如:’#’ s='abbadcacda’先转化成s_new=$#a#b#b#a#d#c#a#c#d#a#\0’(加粗的是边界)
这样原串中的偶回文(abba)与奇回文(adcacda),变成了(#a#d#d#a#)与(#a#d#c#a#c#d#a#)两个奇回文。
定义数组p,用p[i]表示以i为中心的最长回文半径。再次举个例子
(图片是借鉴了他人的)
定义两个变量mx和id。mx就是以id为中心的最长回文右边界,也就是mx=id+p[id],随后我们需要mx做出它的最大贡献。
假设我们在求p[i](以i为中心的最长回文半径),如果i<mx(如上图),那么我们就用mx和j来更新到我们已知的可以更新的最大长度,代码如下:
if(i<mx) p[i]=min(p[2*id-i],mx-i);
2*id-i是i关于id的对称点(上图j)(证明:i-id=id-j),而p[j]表示以j为中心的最长回文半径,这样我们就可以利用p[j]和mx加快速度了。
为什么要用p[j]和mx-i取min来更新呢?
首先我们想一下,p[j](以j为中心的最长回文半径)是已经知道了(因为是从前面扫过来的),若是p[j]>mx-i,我们是可以知道以j为中心,以mx的对称点到j的距离为半径形成的回文字符串是肯定存在的,并且id的左边直到mx的对称点与id的右边直到mx是对应的,所以mx是i目前可以更新到的最大回文半径;(还不明白的话就停下来画图好好想想)
若p[j]<mx-i,证明j的回文半径不到mx的对称点到j的距离,再次通过(id的左边直到mx的对称点与id的右边 直到mx是对应的),所以p[i]=p[j]。
但是取完min并不是最大的回文半径,接下来的就暴力搜就好了
代码
#include<bits/stdc++.h>
using namespace std;
char s[1100000];
char sn[1100000];
int a[1100000];
int ycl()
{int len=strlen(s);sn[0]='$';sn[1]='#';int sum=2;for(int i=0;i<=len;i++){sn[sum++]=s[i];sn[sum++]='#';}sn[sum]='\0';return sum;
}
int mlc()
{int cd=ycl();int mx=0,maxlen=-1,id;for(int i=1;i<=cd;i++){if(i<mx)a[i]=min(a[id*2-i],mx-i);else a[i]=1;while(sn[i-a[i]]==sn[a[i]+i])a[i]++;if(mx<a[i]+i){id=i;mx=a[i]+i;}maxlen=max(maxlen,a[i]-1);}return maxlen;
}
int main()
{scanf("%s",s);printf("%d",mlc());return 0;
}
Manacher(马拉车)相关推荐
- 【算法】Manacher(马拉车)算法
原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...
- Manacher马拉车算法求最长回文子串
终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...
- 【Algorithms】Manacher 马拉车
问题链接: https://www.luogu.com.cn/problem/P3805 PART 1.回文串的中心问题: 形如aba , abba[下文称作有两个中心的回文(子)串]都算是回文串. ...
- Manacher(马拉车)算法—简略讲解
这是一篇菜鸡的算法小笔记!希望你喜欢! 前言 马拉车算法是用来查找一个字符串的最长回文子串的线性方法,是一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到 ...
- manacher马拉车算法
算法讲解 算法讲解1 #include <iostream> #define maxn 10e+6; using namespace std; char s[maxn],str[maxn* ...
- manacher(马拉车)算法详解
manacher算法,用于求字符串中最长回文串.凡是涉及暴力枚举,一般都会超时,尤其当考虑回文串时,必须前后一起判断,复杂度太高.这时,manacher算法在O(n)时间里解决问题.下面看算法. 回文 ...
- ACM-ICPC 2018 南京赛区网络预赛 I.Skr(Manacher马拉车+Hash哈希/回文树)
题目 给一个只由数字构成的字符串s(|s|<=2e6) 求s的所有本质不同字符串之和%1e9+7, 每一个不同字符串的贡献为其十进制下的值 思路来源 https://blog.csdn.net/ ...
- (manacher)马拉车算法专题题目
manacher算法用来求解回文串问题,时间复杂度为O(n). 不懂的先可以去练习下模板板子题,求最长回文串 传送门P3501 [POI2010]ANT-Antisymmetry 这一题他给的是一个新 ...
- Manacher (马拉车)算法
Manacher于1975年发现了一种线性时间算法,可以在列出给定字符串中从任意位置开 始的所有回文子串.同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂 度是线性的.那他是怎样实现的呢, ...
最新文章
- LeetCode 104. Maximum Depth of Binary Tree--二叉树高度--递归或迭代--C++,Python解法
- 冷热分离和直接使用大数据库_中台有“数”:大数据技术为苏宁818保驾护航
- Linux 内核超时导致虚拟机无法正常启动
- delphi中的dbgrid使用
- 网站的容错性设计原则
- Linux基本C编程fork、signal、time以及用printf在终端打印一个GUI窗口 - 使用cygwin
- MyBatis配置项--properties
- ANDROID: 超级好用的ADB FORWARD命令
- mysql中update實現子查詢的方法
- ios系统python编译器_MacBook如何安装Python编译器-百度经验
- Django学习---原生ajax
- Java中锁的使用和实现
- System.arraycopy详解
- leetcode938.RangeSumofBST
- C++封装SQLite实例六
- HTML基础___CSS样式表__上 第九天
- SQLite数据库知识
- 查询学过“叶平”老师所教的所有课的同学的学号、姓名
- Chrome浏览器取色器
- sqlserver 包含关系