Manacher算法求最长回文字串

算法思路

按照惯例((・◇・)?),这里只是对算法的一些大体思路做一个描述,因为找到了相当好理解的博客可以参考(算法细节见参考文章)。

一般而言,我们的判断回文算法的思想是从一个点开始向两边拓展直到无法拓展为止,这个时候就得到了回文串的长度,但这个算法的时间复杂度是\(O(n^2)\)的。在这个算法进行的过程中,我们有可能会不断地拓展了重复的位置而产生重复计算,升高了时间复杂度。马拉车算法通过充分利用已经遍历过的信息,尽量不会重复去遍历已知信息的区段,而且利用一定的空间来记录信息,是一种空间换时间的做法。所谓利用信息,实际上是利用回文串本身的性质,具体的,是一个回文串包含回文字串时的关于对称轴对称的性质。分情况进行了不同处理。

同时,为了避免代码的重复冗余,在原回文串中加入了'#','$'等字符,使奇偶统一讨论,而且能够较为方便的找回对应于原串的信息。

代码

#include <iostream>
#include <cstring>
#define max_n 1005
using namespace std;
int p[max_n];//p[i]表示以i为中心的最长回文的半径
char s[max_n];//记录原串
char t[max_n];//经处理的串
int center = -1;//记录最长回文子串在原串中的起始位置
int max_len = -1;//记录最长回文字串的长度
int Init()//处理原串
{
int len = strlen(s);
t[0] = '$';
t[1] = '#';
int j = 2;
for(int i = 0;i<len;i++)
{
t[j++] = s[i];
t[j++] = '#';
}
t[j] = '\0';
return j;
}
int manacher()
{
int len = Init(); int id;//当前回文子串中心
int mx = 0;//当前回文子串右端点(不包含)
for(int i = 0;i<len;i++)
{
if(i<mx)
{
p[i] = min(p[2*id-i],mx-i);//包含了两种情况
}
else
{
p[i] = 1;//一种情况
}
while(t[i+p[i]]==t[i-p[i]])
{
p[i]++;//看是否还可拓展
}
if(mx<i+p[i])//更新回文子串中心和右端
{
id = i;
mx = i+p[i];
}
if(max_len<p[i]-1)
{
max_len = p[i]-1;//更新最长回文子串长度
center = (i-p[i])/2;//及起始点
}
}
return max_len;
}
int main()
{
cin >> s;
cout << manacher() << endl;
for(int i = center;i<max_len;i++)
{
cout << s[i];
}
cout << endl;
return 0;
}

实例

这里给一个实例:

abbaho

转化后为:$#a#b#b#a#h#o#,可尝试照着代码分析一下,看看mx和id是怎么变化的,对应情况又是怎么处理的

处理串和原串的对应关系

这里说一下处理后的串的信息怎么和原来的串对应上。

这里就要举栗子啦。

原串是abbaho,处理后$#a#b#b#a#h#o#,看中间的#的位置5,p[5]=5,此时原串的回文长度是4,发现4=p[5]-1;起始位置是0,发现(5-p[5])/2=0

再来看看anppnb,处理后为$#a#n#p#p#n#b#,中间#的位置是7,p[7]=5,此时原串回文长度是4,发现4=p[7]-1;起始位置是1,发现(7-p[7])/2=1

于是不完全归纳出:

原串回文长度=p[处理串的回文中心位置]-1

原串回文起始位置=(处理串回文中心位置-p[处理串回文中心位置])/2

参考文章

原串处理串对应关系请见:

Grandyang,Manacher's Algorithm 马拉车算法,https://www.cnblogs.com/grandyang/p/4475985.html

算法流程讲解请见:

BIT祝威 ,[译+改]最长回文子串(Longest Palindromic Substring) Part II,https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

具体的算法分析请见:

刘毅,Manacher 算法 ,https://subetter.com/algorithm/manacher-algorithm.html

Manacher算法(马拉车)求最长回文子串的更多相关文章

  1. manacher算法_求最长回文子串长度

    很好的总结,转自: http://blog.csdn.net/dyx404514/article/details/42061017 总结为:两大情况,三小情况. 两大情况:I. i <= p 1 ...

  2. manacher算法学习(求最长回文子串长度)

    Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...

  3. Manacher模板( 线性求最长回文子串 )

    模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...

  4. Manacher算法讲解——字符串最长回文子串

    引 入 引入 引入 Manachar算法主要是处理字符串中关于回文串的问题的,这没什么好说的. M a n a c h e r 算 法 Manacher算法 Manacher算法 朴素 求一个字符串中 ...

  5. 【Manacher算法】求最长回文串的优秀算法

    先贴一下代码~ //by 减维 #include<cstdio> #include<iostream> #include<cstring> #include< ...

  6. [hdu 3068] Manacher算法O(n)最长回文子串

    一个不错的讲解:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.05.md # ...

  7. Manacher算法:求解最长回文字符串,时间复杂度为O(N)

    原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...

  8. hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]

    传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...

  9. PAT甲题题解-1040. Longest Symmetric String (25)-求最长回文子串

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789177.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  10. hdu 3068 最长回文(manachar求最长回文子串)

    题目连接:hdu 3068 最长回文 解题思路:通过manachar算法求最长回文子串,如果用遍历的话绝对超时. #include <stdio.h> #include <strin ...

随机推荐

  1. linux下找到JVM占用资源最高的线程

    linux的top命令不仅可以看线程的资源占用,还可以看进程下线程的资源占用,结合对应的java命令可以定位到具体有问题的Java代码,以找出占用CPU最高的线程为例: 第一步: 通过 top命令查找 ...

  2. [LeetCode] 277. Find the Celebrity 寻找名人

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  3. [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...

  4. NOI 2010 海拔(最小割转最短路)

    题意 https://www.lydsy.com/JudgeOnline/problem.php?id=2007 思路 首先可以发现一个结论,每个位置的海拔只有能是 \(0\) 和 \(1\) ,然后 ...

  5. C# HTTP系列3 HttpWebRequest.ContentType属性

    系列目录     [已更新最新开发文章,点击查看详细] 获取或设置请求的 Content-type HTTP 标头的值.默认值为null. 常见的请求内容类型为以下几种: /// <summar ...

  6. docker 安装 apollo

    apollo作为携程开源的配置中心,很多大厂在使用,在此记录下安装历程 服务器环境: 安装mysql 1.拉取镜像 docker pull idoop/docker-apollo 2.新建3个数据库, ...

  7. 百度语音识别在ROS下的应用-导航

    先去wiki下载百度的ros语音识别包:http://wiki.ros.org/baidu_speech 里面包含语音识别voice和speak的node节点,不过voice_node里面有一个小的错 ...

  8. 改写URL的查询字符串QUERY_STRING[URL重定向问号问题](转)

    查询字符串是指URL请求中"问号"后面的部分.比如,http://mysite/?foo=bar 中粗体部分就是查询字符串,其中变量名是foo,值是bar. 'last|L' (最 ...

  9. Android 5.0以下系统支持TLS 1.1/1.2协议版本

    一.背景 项目中,客户端与服务端之间普遍使用Https协议通信,突然接到测试同事反馈Android5.0以下手机上,App测试服使用出现问题,出现SSL handshake aborted错误信息,但 ...

  10. 从 SOA 到微服务,企业分布式应用架构在云原生时代如何重塑?

    作者 | 易立 阿里云资深技术专家 导读:从十余年前的各种分布式系统研发到现在的容器云,从支撑原有业务到孵化各个新业务,企业的发展离不开统一的.与时俱进的技术架构.本篇文章从企业分布式应用架构层面介绍 ...