本文部分图片来源 代码来源(代码是学姐哒..

一、引入

Manacher算法是用来求最长回文子串的算法,时间复杂度O(n)。

回文子串指的是''aacaa'',''noon'',这种正着反着读都一样的。

二、构造字符串

朴素的求法是O(n^2),以某个字符为中心,向左右扩展,如下图所示。

对于长度为奇数的字符串是可以枚举回文串的中心的,那么偶数的呢?

我们在字符的空里插入其他不在字符串中出现过的字符,如’#‘。

如字符串acca,变为$a#c#c#a#,为了避免出现错误,我们不让首字符等于尾字符。

所以在开头插入的字符为‘$’。

三、引进Len数组

假设输入的字符串为s。

Len[i]表示以i为中心的最长的回文半径的长度(包括i)。

如果以str[i]为中心的回文串的范围为[l,r],那么Len[i]=r-i+1。

Len数组的性质,Len[i]-1为该回文串在原串s中的长度。

证明:2*Len[i]-1表示带’#‘的回文串的长度,’#‘的个数一共有Len[i]个,那么回文串

的长度就是2*Len[i]-1-Len[i]=Len[i]-1。

如图所示:

还要介绍几个变量的意义:现在从左到右扫字符串计算Len数组,mx表示目前为止的回文串能覆盖的最右端点,

id表示最后更新mx的i的位置。

四、计算Len数组

由于回文串有对称的特点,那么对于Len数组的求法,我们尽量的抄之前与该字符对称字符的Len[]。

另外,我们约定mx是开区间的,也就是说覆盖的最右端点为mx-1,这是对于下面的Manacher代码模板来约定的。

怎样通过‘抄’来计算Len数组呢?

假设现在正在计算Len[i]的值。

A:当i<mx。

(1):当Len[j]<=mx-i时,那么以i为中心的回文串至少和以j为中心的回文串相等。

也就是Len[i]>=Len[j],所以我们先直接抄过Len[j]赋值给Len[i],然后再暴力,看能否再扩展。

更新mx和id。

(2):当Len[j]>mx-i时,那么i+Len[j]已经大于mx,我们对于mx向右的地方是未知的,

所以不能直接把Len[j]抄过来,只能让Len[i]先等于mx-i,这是一定对的,然后在暴力扩展。

 B:当i>=mx,也就是说Len[i]没有办法从j这里抄过来,需要暴力计算。

五、模板

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1e6+;
char s[maxn*],str[maxn*];
int Len[maxn*],len; void getstr()
{
int k=;
str[k++]='$';
for(int i=;i<len;i++)
str[k++]='#',
str[k++]=s[i];
str[k++]='#';
len=k;
}
void Manacher()
{
getstr();
int mx=,id;
for(int i=;i<len;i++)
{
if(mx>i) Len[i]=min(Len[*id-i],mx-i);
else Len[i]=;
while(str[i+Len[i]]==str[i-Len[i]])
Len[i]++;
if(Len[i]+i>mx)
mx=Len[i]+i,id=i;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",&s);
len=strlen(s);
Manacher();
int ans=;
for(int i=;i<len;i++) ans=max(ans,Len[i]);
printf("%d\n",ans-);
}
return ;
}

模板需要注意的就是数组的大小了。

六、习题

BZOJ 2342: [Shoi2011]双倍回文

[BZOJ2565] 最长双回文串

[BZOJ3790] 神奇项链

[BZOJ2160]拉拉队排练

【学习笔记】Manacher算法的更多相关文章

  1. 学习笔记 - Manacher算法

    Manacher算法 - 学习笔记 是从最近Codeforces的一场比赛了解到这个算法的~ 非常新奇,毕竟是第一次听说 \(O(n)\) 的回文串算法 我在 vjudge 上开了一个[练习],有兴趣 ...

  2. [ML学习笔记] XGBoost算法

    [ML学习笔记] XGBoost算法 回归树 决策树可用于分类和回归,分类的结果是离散值(类别),回归的结果是连续值(数值),但本质都是特征(feature)到结果/标签(label)之间的映射. 这 ...

  3. 学习笔记——EM算法

    EM算法是一种迭代算法,用于含有隐变量(hidden variable)的概率模型参数的极大似然估计,或极大后验概率估计.EM算法的每次迭代由两步组成:E步,求期望(expectation):M步,求 ...

  4. 数据挖掘学习笔记--AdaBoost算法(一)

    声明: 这篇笔记是自己对AdaBoost原理的一些理解,如果有错,还望指正,俯谢- 背景: AdaBoost算法,这个算法思路简单,但是论文真是各种晦涩啊-,以下是自己看了A Short Introd ...

  5. 学习笔记-KMP算法

    按照学习计划和TimeMachine学长的推荐,学习了一下KMP算法. 昨晚晚自习下课前粗略的看了看,发现根本理解不了高端的next数组啊有木有,不过好在在今天系统的学习了之后感觉是有很大提升的了,起 ...

  6. Java学习笔记——排序算法之快速排序

    会当凌绝顶,一览众山小. --望岳 如果说有哪个排序算法不能不会,那就是快速排序(Quick Sort)了 快速排序简单而高效,是最适合学习的进阶排序算法. 直接上代码: public class Q ...

  7. Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)

    春蚕到死丝方尽,蜡炬成灰泪始干 --无题 这里介绍两个比较难的算法: 1.堆排序 2.分治并归排序 先说堆. 这里请大家先自行了解完全二叉树的数据结构. 堆是完全二叉树.大顶堆是在堆中,任意双亲值都大 ...

  8. Java学习笔记——排序算法之希尔排序(Shell Sort)

    落日楼头,断鸿声里,江南游子.把吴钩看了,栏杆拍遍,无人会,登临意. --水龙吟·登建康赏心亭 希尔算法是希尔(D.L.Shell)于1959年提出的一种排序算法.是第一个时间复杂度突破O(n²)的算 ...

  9. 算法笔记--manacher算法

    参考:https://www.cnblogs.com/grandyang/p/4475985.html#undefined 模板: ; int p[N]; string manacher(string ...

  10. 学习笔记——SM2算法原理及实现

    RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosyste ...

随机推荐

  1. Microsoft.VisualStudio.Web.PageInspector.Loader

    未能加载文件或程序集"Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, P ...

  2. Spring_使用 NamedParameterJdbcTemplate

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?><beans xml ...

  3. [POI2006]MET-Subway

    Description 给出一棵N个结点的树,选择L条路径,覆盖这些路径上的结点,使得被覆盖到的结点数最多. Input 第一行两个正整数N.L(2 <= N <= 1,000,000, ...

  4. Java 多线程 - 转载

    下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编 ...

  5. IE报错:缺少标识符、字符串或数字

    在调试ExtJS程序时,在firefox和chrome上都能显示,但一到IE上就报错,后来从左下角的JS报错提示中才发现,原来是JS代码中多加了个逗号. menu: { items: [{ text: ...

  6. Delphi_时间间隔

    1. var dtOnlineDateTime, dt: TDateTime; begin dt := StrToDateTime('2017/6/28 16:41:30'); dtOnlineDat ...

  7. Dynamo论文介绍

    http://catkang.github.io/2016/05/27/dynamo.html Dynamo是Amazon开发的分布式存储系统,本文是阅读Dynamo论文后的总结:Dynamo: Am ...

  8. node 模块部分介绍

    chai  断言框架 mocha mochawesome  对mocha 定制报告,生成完整成熟的报告. node-fetch  服务器版fetch superagent  是node 客户端请求代理 ...

  9. 反汇编工具 objdump的使用简介

    arm-linux-objdump -D led.elf > led_elf.dis objdump是gcc工具链中的反汇编工具,作用是由编译链接好的elf格式的可执行程序反过来得到反汇编代码 ...

  10. 微信小程序入门四: 导航栏样式、tabBar导航栏

    实例内容 导航栏样式设置 tabBar导航栏 实例一:导航栏样式设置 小程序的导航栏样式在app.json中定义. 这里设置导航,背景黑色,文字白色,文字内容测试小程序 app.json内容: { & ...