manacher算法讲解
2016-02-21 21:02
183 查看
一.manacher算法求出的是什么?
mancher算法求解出一个字符串中,以每一个字符为中心的回文的最长长度。复杂度是o(n)
二.manacher算法是如何实现的?
1.首先需要对一个字符串进行预处理
设原字符串为t,处理得到的字符串为s。为了字符串从零开始,另字符串s[0] = ‘&’(为保证与之后的字符都不相同)
然后分别在开头,每个字符之间,以及最后,添加一个与t中字符都不同的字符,一般为‘#’
那么为什么要进行预处理呢?使得长度为奇数和偶数回文串都变成长度为偶数的字符串。
2.求解以每个字符为中心,回文的最长长度
首先我们假设i之前的回文长度都已经求出了。以i为中心的回文串的长度用P[i]存储。P[i] -1就是该回文子串在原串中的长度(包括‘#’)最远匹配到(从一个位置id开始,两侧字符相等的最远位置)的字符串的位置为mx,使得位置最远的回文串是以id为中心的。
下面是该算法的关键
if(mx > i) p[i] = min(mx - i,p[2 * id - i])
下面图片来自:http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
当mx - i > p [j]
由图可知,以id为中心,向右到mx是回文串,所以两侧是对称的,因为当p[i] = p[j]时,也未超过mx的大小,所以p[i]一定 == p[j] (如果p[i] > p[j]根据对称,p[j]就就应该变大)
当mx - i <= p[j]
这种时候需要对大于mx的地方进行匹配
ps:如果mx <= i,还没匹配到这里的时候要对p[i] 初始化为1,要从头开始匹配
下面是manacher算法的代码
预处理:void init()
{
s[0] = '&';
for(int i = 0; i < n; i ++)
{
s[i * 2 + 2] = t[i];
s[i * 2 + 1] = '#';
}
s[n * 2 +1] = '#';
}
mancher算法求解出一个字符串中,以每一个字符为中心的回文的最长长度。复杂度是o(n)
二.manacher算法是如何实现的?
1.首先需要对一个字符串进行预处理
设原字符串为t,处理得到的字符串为s。为了字符串从零开始,另字符串s[0] = ‘&’(为保证与之后的字符都不相同)
然后分别在开头,每个字符之间,以及最后,添加一个与t中字符都不同的字符,一般为‘#’
那么为什么要进行预处理呢?使得长度为奇数和偶数回文串都变成长度为偶数的字符串。
2.求解以每个字符为中心,回文的最长长度
首先我们假设i之前的回文长度都已经求出了。以i为中心的回文串的长度用P[i]存储。P[i] -1就是该回文子串在原串中的长度(包括‘#’)最远匹配到(从一个位置id开始,两侧字符相等的最远位置)的字符串的位置为mx,使得位置最远的回文串是以id为中心的。
下面是该算法的关键
if(mx > i) p[i] = min(mx - i,p[2 * id - i])
下面图片来自:http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
当mx - i > p [j]
由图可知,以id为中心,向右到mx是回文串,所以两侧是对称的,因为当p[i] = p[j]时,也未超过mx的大小,所以p[i]一定 == p[j] (如果p[i] > p[j]根据对称,p[j]就就应该变大)
当mx - i <= p[j]
这种时候需要对大于mx的地方进行匹配
ps:如果mx <= i,还没匹配到这里的时候要对p[i] 初始化为1,要从头开始匹配
下面是manacher算法的代码
预处理:void init()
{
s[0] = '&';
for(int i = 0; i < n; i ++)
{
s[i * 2 + 2] = t[i];
s[i * 2 + 1] = '#';
}
s[n * 2 +1] = '#';
}
void gethuiwen() { int mx = 0,id = 0; for(int i = 1; i < n * 2 + 2;i ++) { if(mx > i) { p[i] = min(p[id * 2 - i],mx - i); } else p[i] = 1; for(;s[p[i] + i] == s[i - p[i]];p[i] ++); if(p[i] + i > mx) { mx = p[i] + i; id = i; } } } //#a#a#a#a#
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析