Manacher算法总结
部分图片转自:http://www.cnblogs.com/grandyang/p/4475985.html
manacher算法(民间称马拉车算法233)是用来找字符串中的最长回文子串的,先来说一下什么是回文串,像这样“abcba”这样一个字符串找到一个中间位置,然后分别向他的左边和右边相等的距离位置的字符是相同的,那么这个字符串就称为回文串,“abcba”这个字符串的len为5是奇数,我们可以找到一个中间字符,然后进行搜索也可以找出来(当然时间复杂度是比较高的),但是当我们遇到一个长度为偶数的字符串时该怎么找中间字符呢,像这样“abccba”,下面我们引入Manacher算法,这是一个可以将长度为奇数或偶数的字符串一起考虑的神奇算法
Manacher算法可以将长度为奇数和偶数的回文串一起考虑:在原字符串的相邻字符串之间插入一个分隔符,字符串的首尾也要分别添加,注意分隔符必须是原字符串中没有出现过的
| 原字符串s | a | b | a | b | c |
| 转换后字符串str | # | a | # | b | # | a | # | b | # | c | # |
一、Len数组的简单介绍
Manacher算法中用到一个非常重要的辅助数组Len[i]表示以str[i]为中心的最长回文子串的最右端到str[i]位置的长度,比如以str[i]为中心的最长回文串是str[l,r],那么Len[i]=r-i+1
| 转换后的字符串str | # | a | # | b | # | a | # | b | # | c | # |
| Len | 1 | 2 | 1 | 4 | 1 | 4 | 1 | 2 | 1 | 2 | 1 |
Len[i]数组有一个性质,Len[i]-1就等于该回文串在原串s中的长度
证明:在转换后的字符串str中,所有的回文串的长度都是奇数,那么对于以str[i]为中心的最长回文串的长度为2*Len[i]-1,其中又有Len[i]个分隔符,所以在原字符串中的长度就是Len[i]-1,那么剩下的工作就是求Len数组
二、Len数组的计算
从左往右开始计算,假设0<=j<=i,那么在计算Len[i]时,Len[j]已经计算过了,设mx为之前计算过的最长回文串的右端点,id为取得这个端点值得位置(那么Len[id]=mx-id+1)
第一种情况:i<=mx.
找到i相对于id的对称位置,设为j,再次分为两种情况:
1、Len[j]<mx-i

mx的对称点为2*id-mx,i和j所包含的范围是2*Len[j]-1
那么说明以j为中心的回文串一定在以id为中心的回文串内部,且i和j关于id对称,由回文串的定义可知,一个回文串反过来仍是回文串,所以以i为中心的回文串长度至少和以i为中心的回文串长度相等,即Len[i]>=Len[j].因为Len[j]<mx-i所以i+Len[j]<mx,由对称性可知Len[i]=Len[j].
2、Len[j]>=mx-i

由对称性说明以i为中心的回文串可能延伸到mx之外,而大于mx的部分我们还没有进行匹配,所以要从mx+1位置开始一个一个匹配直到失配,从而更新mx和对应的id以及Len[i]
第二种情况,i>mx
如果i比mx还大,说明对于中点为i的回文串一点都没匹配,这个时候只能一个个匹配(滑稽),匹配完成后更新mx的位置和对应的id及Len[i].
代码实现:
#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 ;
}
Manacher算法总结的更多相关文章
- HDU3068 回文串 Manacher算法
好久没有刷题了,虽然参加过ACM,但是始终没有融会贯通,没有学个彻底.我干啥都是半吊子,一瓶子不满半瓶子晃荡. 就连简单的Manacher算法我也没有刷过,常常为岁月蹉跎而感到后悔. 问题描述 给定一 ...
- manacher算法专题
一.模板 算法解析:http://www.felix021.com/blog/read.php?2040 *主要用来解决一个字符串中最长回文串的长度,在O(n)时间内,线性复杂度下,求出以每个字符串为 ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
- 1089 最长回文子串 V2(Manacher算法)
1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaaa ...
- 51nod1089(最长回文子串之manacher算法)
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...
- LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2
https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhor ...
- 求最长回文子串:Manacher算法
主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...
- 【转】最长回文子串的O(n)的Manacher算法
Manacher算法 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长.这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文 ...
- Manacher算法
Manacher算法是求回文串最高效的算法,能在线性时间内求出以每一个字符为中心的最长回文串. 首先,我们都能想出$O(N^2)$求出每一个字符为中心的最长回文串的算法.那么我们考虑这样一种情况. ...
- 字符串匹配--manacher算法模板
manacher算法主要是处理字符串中关于回文串的问题的,它可以在 O(n) 的时间处理出以字符串中每一个字符为中心的回文串半径,由于将原字符串处理成两倍长度的新串,在每两个字符之间加入一个特定的特殊 ...
随机推荐
- 第八周 yukun 20155335
- 逃生(HDU4857 + 反向拓扑排序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 题面是中文题面,就不解释题意了,自己点击链接去看下啦~这题排序有两个条件,一个是按给定的那个序列 ...
- vue双向数据绑定的原理-object.defineProperty() 用法
有关双向数据绑定的原理 关于数据双向绑定的理解:利用了 Object.defineProperty() 这个方法重新给对象定义了新属性,在操作新属性分别为为获取属性值(调用get方法)和设置属性值(调 ...
- 对象方法、类方法、原型方法 && 私有属性、公有属性、公有静态属性
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- js中的for in 循环
1.数组 使用for in 遍历数组时,其索引被视为对象的属性,从而直接输出数组的索引 var arr = ["a","b","c"]; f ...
- ms17010利用失败解决一则
没有反弹得到session并且提示如下: [-] 10.0.131.2:445 - Service failed to start, ERROR_CODE: 216 换了一个payload set p ...
- mac系统中实现vitualBox中访问内网端口
第一步,增加外网网段 打开vitualbox后,按管理菜单,点击->主机网络管理器,如图1所示.点击创建,创建下个网络主机. 图1 然后,关掉虚拟机,虚拟机的设置中,找到网络选项卡,然后点击网络 ...
- 小白成长记-----python实现注册的小程序
# 3.写一个注册的程序,输入username,密码,# 密码确认,输入的账号和密码不能为空,两次输入密码必须一致,# 用户名不能重复,错误次数四次 .注册成功提示成功# 把注册账号密码信息的写到文件 ...
- 关于大O法的几点解释
大O表示法指出算法有多快.例如,假设列表包含n个元素.简单查找需要检查每个元素,因此需要执行n次操作.使用大O表示法,这个运行时间为O(n).主要单位不是秒啊,大O表示法值得并非以秒为单位的速度,而是 ...
- linux命令(34):less命令
1.命令格式: less [参数] 文件 2.命令功能: less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会 ...