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算法——回文串计算的高效算法的更多相关文章

  1. Girls' research - HDU 3294 (Manacher处理回文串)

    题目大意:给以一个字符串,求出来这个字符串的最长回文串,不过这个字符串不是原串,而是转换过的,转换的原则就是先给一个字符 例如 'b' 意思就是字符把字符b转换成字符 a,那么c->b, d-& ...

  2. leetcode:Palindrome Number (判断数字是否回文串) 【面试算法题】

    题目: Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could neg ...

  3. hdu 3294 manacher 求回文串

    感谢: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ O(n)求给定字符串的以每个位置为中心的回文串长度. 中心思想:每次计算位 ...

  4. HDU 5340——Three Palindromes——————【manacher处理回文串】

    Three Palindromes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  5. HDU 5371 Hotaru's problem (Manacher,回文串)

    题意:给一个序列,找出1个连续子序列,将其平分成前,中,后等长的3段子序列,要求[前]和[中]是回文,[中]和[后]是回文.求3段最长为多少?由于平分的关系,所以答案应该是3的倍数. 思路:先Mana ...

  6. 算法 -- 四种方法获取的最长“回文串”,并对时间复杂进行分析对比&PHP

    https://blog.csdn.net/hongyuancao/article/details/82962382 “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就 ...

  7. 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长度 ...

  8. 最长回文子串问题 O(n)算法 manacher URAL1297 HDU3068

    先来看一道简单的题,ural1297 给定一个1000长度的字符串,求最长回文子串. 看起来很Naive,乱搞一下,O(n^2)都可以解决. 再来看这个题 HDU3068 120个110000长度的字 ...

  9. 马拉车,O(n)求回文串

    马拉车,O(n)求回文串 对整个马拉车算法步骤做个总结: 第一步:将每个原字母用两个特殊字符包围如: aaa --> #a#a#a# abab -->#a#b#a#b 同时可以由这个翻倍的 ...

随机推荐

  1. 【SpringMVC】SpringMVC 拦截器

    SpringMVC 拦截器 文章源码 拦截器的作用 SpringMVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理. 谈到拦截器,还有另外一个概 ...

  2. 前端面试:Http协议与浏览器

    Http与Https的区别 Http是明文传输的,Https协议是在Http协议上添加了SSL的加密协议,可以进行加密传输和身份验证. 其实就是说Http对网络传输完全是裸奔状态,也就没办法防范中间人 ...

  3. 【Java】一个简单的Java应用程序

    简单记录,Java 核心技术卷I 基础知识(原书第10 版) 一个简单的Java应用程序"Hello, World!" Hello, World! Goodbye,World! 一 ...

  4. 【MySQL】Last_SQL_Errno: 1594Relay log read failure: Could not parse relay log event entry...问题总结处理

    备库报错: Last_SQL_Errno: 1594 Last_SQL_Error: Relay log read failure: Could not parse relay log event e ...

  5. 【Linux】tcpdump

    tcpdump介绍 tcpdump 是一个运行在命令行下的抓包工具.它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包.tcpdump 适用于 大多数的类Unix系统操作系统 ...

  6. oracle rac切换到单实例DG后OGG的处理

    在RAC切换到单实例DG后,将OGG目录复制过去,在使用alter extract ext_name,begin now的时候报错 2016-04-10 11:27:03 WARNING OGG-01 ...

  7. oracle move表空间(分区表,索引)

    1.修改分区表分区表空间 SELECT 'ALTER TABLE ' || table_owner || '.' || TABLE_NAME || ' MOVE PARTITION ' || PART ...

  8. SEO大杀器rendertron安装

    前段时间做SEO的优化,使用的是GoogleChrome/rendertron,发现这个安装部署的时候还是会有一些要注意的地方,做个记录 为什么要使用rendertron 目前很多网站都是使用 vue ...

  9. 扩展:Flash消息

    扩展:Flash消息 flash存值之后只能取一次 from flask import Flask,render_template,flash,get_flashed_messages,session ...

  10. ORB-SLAM2-tracking线程

    tracking线程 Tracking线程的主要工作是从图像中提取ORB特征,根据上一帧进行姿态估计或者进行通过全局重定位初始化位姿,然后跟踪已经重建的局部地图,优化位姿,再根据一些规则确定新的关键帧 ...