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(马拉车)相关推荐

  1. 【算法】Manacher(马拉车)算法

    原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...

  2. Manacher马拉车算法求最长回文子串

    终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...

  3. 【Algorithms】Manacher 马拉车

    问题链接:  https://www.luogu.com.cn/problem/P3805 PART 1.回文串的中心问题: 形如aba , abba[下文称作有两个中心的回文(子)串]都算是回文串. ...

  4. Manacher(马拉车)算法—简略讲解

    这是一篇菜鸡的算法小笔记!希望你喜欢! 前言 马拉车算法是用来查找一个字符串的最长回文子串的线性方法,是一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到 ...

  5. manacher马拉车算法

    算法讲解 算法讲解1 #include <iostream> #define maxn 10e+6; using namespace std; char s[maxn],str[maxn* ...

  6. manacher(马拉车)算法详解

    manacher算法,用于求字符串中最长回文串.凡是涉及暴力枚举,一般都会超时,尤其当考虑回文串时,必须前后一起判断,复杂度太高.这时,manacher算法在O(n)时间里解决问题.下面看算法. 回文 ...

  7. ACM-ICPC 2018 南京赛区网络预赛 I.Skr(Manacher马拉车+Hash哈希/回文树)

    题目 给一个只由数字构成的字符串s(|s|<=2e6) 求s的所有本质不同字符串之和%1e9+7, 每一个不同字符串的贡献为其十进制下的值 思路来源 https://blog.csdn.net/ ...

  8. (manacher)马拉车算法专题题目

    manacher算法用来求解回文串问题,时间复杂度为O(n). 不懂的先可以去练习下模板板子题,求最长回文串 传送门P3501 [POI2010]ANT-Antisymmetry 这一题他给的是一个新 ...

  9. Manacher (马拉车)算法

    Manacher于1975年发现了一种线性时间算法,可以在列出给定字符串中从任意位置开 始的所有回文子串.同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂 度是线性的.那他是怎样实现的呢, ...

最新文章

  1. LeetCode 104. Maximum Depth of Binary Tree--二叉树高度--递归或迭代--C++,Python解法
  2. 冷热分离和直接使用大数据库_中台有“数”:大数据技术为苏宁818保驾护航
  3. Linux 内核超时导致虚拟机无法正常启动
  4. delphi中的dbgrid使用
  5. 网站的容错性设计原则
  6. Linux基本C编程fork、signal、time以及用printf在终端打印一个GUI窗口 - 使用cygwin
  7. MyBatis配置项--properties
  8. ANDROID: 超级好用的ADB FORWARD命令
  9. mysql中update實現子查詢的方法
  10. ios系统python编译器_MacBook如何安装Python编译器-百度经验
  11. Django学习---原生ajax
  12. Java中锁的使用和实现
  13. System.arraycopy详解
  14. leetcode938.RangeSumofBST
  15. C++封装SQLite实例六
  16. HTML基础___CSS样式表__上 第九天
  17. SQLite数据库知识
  18. 查询学过“叶平”老师所教的所有课的同学的学号、姓名
  19. Chrome浏览器取色器
  20. sqlserver 包含关系

热门文章

  1. 如何使用yum工具从iso镜像文件上安装
  2. 智慧灯杆基于边缘计算网关的单灯远程控制功能
  3. AntDB 落地某省电信大数据中心项目的性能优化案例分享
  4. TP、TN、FP、FN解析
  5. SpringCloud学习笔记 - 消息总线 - Spring Cloud Bus
  6. 富斯i6航模遥控器翻译
  7. 机器学习——Naive Bayes算法
  8. 利用训练数据建立一个简单的分类器
  9. 期刊为何发表造假论文?
  10. RichEdit读取rtf格式