算法学习:manacher
【没有前置知识】
【解决的问题】
大多数都和回文串有关
例如:
字符串中长度最长的回文串
【算法学习】
manacher优秀的地方在于,他能够在线性时间内求出每个字符所对应的以其自身为中心的最长回文串长度
(请牢记这个目的)
先来讲朴素算法:
从1~n,对每个字符都从其自身开始,向两边递推,如果左右两边字符相同,范围+1,长度+2
这样的复杂度是n^2的
而 manacher 的优化方式和 kmp 有所类似,都是利用之前已经匹配过和得到过的信息,简化当前的运算
回文串有两种,一种是奇数长度一种是偶数长度,显然他们是需要被区别对待的
但是在理解了manacher的本质之后,我们只需要做微小改动就能够同时解决这两个问题
首先引入 l 和 r ,代表当前已经找到的回文串中,右端点最右的回文串的左右端点,初始为 0 和 1
设数组d为我们所需要求取的数组,即每个字符所对应的以其自身为中心的最长回文串长度
假设我们现在要求d [ i ] 的值,而 d [ i ] 之前的值已经求出来了
当我们现在所求的 i < r 时,即现在这个字符是在一个回文串中的时候
我们就可以利用这个信息,来处理他
求在(l,r)这个回文串中和他位置对称的 d [ j ]
因为在回文串中,所以 d [ i ] 和 d[ j ] 两边一定长度内的字符是相同的
而这个一定长度就是,以 s [ j ] 为中心的回文串的长度,可能超过了(l,r)的范围
所以不能看作回文串,只有在这个范围内才能看作回文串
所以我们能够借用这个因素得到的 d [ i ] 两边的回文串长度就是min( d [ j ] , j + 1 - r )
得到这个长度之后,我们为了得到最终答案,还需要继续扩展 以 s [ i ] 为中心的回文串
所以用朴素算法继续扩展
在扩展过程中,如果以 s [ i ] 为中心的回文串的最右边端点超过了 r
我们就需要更新 l , r ,保证他们所代表的意义不变
然后我们在来讨论之前没有谈论的两种回文串的问题
常见的方法是在每两个字符间都插入一个不可能出现的字符,这样就能够将所有的奇偶字符转化统一
也还有另外一种方法
通过访问双倍长度,枚举每一种情况
实际上和插入字符类似,只不过是把字符插入这种操作
通过数字下标的形式取代
建议画图理解
【复杂度】
实际上我们可以看出来,至始至终每次都是 r 在不断的右移,并没有出现重复,所以最后的复杂度和字符串的长度等同
1 void manacher(char *s,int n,int *d) 2 { 3 d[0] = 1; 4 for (int i = 1,j = 0; i < (n << 1) - 1; i++) 5 { 6 int p = i >> 1, q = i - p; 7 int r = ((j + 1) >> 1) + d[j] - 1; 8 if (r < q) 9 d[i] = 0; 10 else 11 d[i] = min(r - q + 1, d[(j << 1) - i]); 12 while (0 <= p - d[i] && q + d[i] < n && s[p - d[i]] == s[q + d[i]]) 13 d[i]++; 14 if (q + d[i] - 1 > r) 15 j = i; 16 } 17 }
void manacher(char *s,int n,int *d) {d[0] = 1;for (int i = 1,j = 0; i < (n << 1) - 1; i++){int p = i >> 1, q = i - p;int r = ((j + 1) >> 1) + d[j] - 1;if (r < q)d[i] = 0;elsed[i] = min(r - q + 1, d[(j << 1) - i]);while (0 <= p - d[i] && q + d[i] < n && s[p - d[i]] == s[q + d[i]])d[i]++;if (q + d[i] - 1 > r)j = i;} }
View Code
转载于:https://www.cnblogs.com/rentu/p/11323543.html
算法学习:manacher相关推荐
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- 算法学习:后缀数组 height的求取
[前置知识] 后缀数组 [定义] [LCP]全名最长公共前缀,两个后缀之间的最长前缀,以下我们定义 lcp ( i , j ) 的意义是后缀 i 和 j 的最长前缀 [z函数] 函数z [ i ] 表 ...
- 拿下斯坦福和剑桥双offer,00后的算法学习之路
董文馨,00后,精通英语,西班牙语.斯坦福大学计算机系和剑桥大学双Offer,秋季将进入斯坦福大学学习. 10岁开始在国外上学:12岁学Scratch: 13岁学HTML & CSS: 14岁 ...
- 好久没有看到这么有建设性德文章,由衷地赞叹《知其所以然地学习(以算法学习为例)》-By 刘未鹏(pongba)
知其所以然地学习(以算法学习为例) By 刘未鹏(pongba) C++的罗浮宫(http://blog.csdn.net/pongba) Updated(2008-7-24):更新见正文部分,有标注 ...
- 原创 | 初学者友好!最全算法学习资源汇总(附链接)
在计算机发展飞速的今天,也许有人会问,"今天计算机这么快,算法还重要吗?"其实永远不会有太快的计算机,因为我们总会想出新的应用.虽然在摩尔定律的作用下,计算机的计算能力每年都在飞快 ...
- 基本算法学习(一)之希尔排序(JS)
参考书: 严蔚敏-数据结构 希尔排序(Shell's Sort) 希尔排序又称"缩小增量排序",归属于插入排序一类,简单来说,和我们的插入排序比,它更快. 奇妙的记忆点: 内排序( ...
- 大顶堆删除最大值_算法学习笔记(47): 二叉堆
堆(Heap)是一类数据结构,它们拥有树状结构,且能够保证父节点比子节点大(或小).当根节点保存堆中最大值时,称为大根堆:反之,则称为小根堆. 二叉堆(Binary Heap)是最简单.常用的堆,是一 ...
- Surf算法学习心得(一)——算法原理
Surf算法学习心得(一)--算法原理 写在前面的话: Surf算法是对Sift算法的一种改进,主要是在算法的执行效率上,比Sift算法来讲运行更快!由于我也是初学者,刚刚才开始研究这个算法,然而网上 ...
- 算法学习:后缀自动机
[前置知识] AC自动机(没有什么关联,但是看懂了会对后缀自动机有不同的理解) [解决问题] 各种子串的问题 [算法学习] 学习后缀自动机的过程中,看到了许多相关性质和证明,但是奈何才疏学浅(lan) ...
最新文章
- 报Java面授班有哪些优势
- python+opencv图像拼接-python opencv 图像拼接的实现方法
- opencv和HALCON坐标系的不同
- oracle 监听主机,Oracle 监听
- 剑指Offer(Java实现)按之字形顺序打印二叉树
- getSystemService() in Android
- 浩然GG和女朋友的游戏 (数学,规律)
- 平面/UI设计师社区网站集设网|让你作品开始发光
- stm32usb转串口驱动_新品推荐:乐扩PCI-E转8口RS-232串口卡 支持短铁片
- 第九章 搭建Hadoop 2.2.0版本HDFS的HA配置
- sql取逗号隔开的值_想学好Excel函数?你得先搞懂函数公式中逗号和星号的区别...
- catia二次开发:人机交互select,start command
- 凉凉!Tumblr 或被 300 万贱卖
- 【黑灰产犯罪研究】恶意点击
- 基于PP-OCR训练表格识别模型
- 【taro】taro如何打开微信小程序
- vue使用echarts-liquidfill水球图不生效
- 用计算机来解锁密码,电脑忘记开机密码怎么办?如何解锁?
- ios html5 拍照旋转,H5 解决ios拍照旋转90度
- VC驿站黑客编程(关机,重启,注销)