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. CF908G New Year and Original Order(DP,数位 DP)

    又一次降智…… (数位 DP 原来可以写这么短,学到了) 问题可以转化为求数位中 $\ge k$ 的有恰好 $j$ 位的数的个数.设为 $c_{j,k}$. 那么答案就是:(考虑把 $k$ 的贡献拆开 ...

  2. 第31课 std::atomic原子变量

    一. std::atomic_flag和std::atomic (一)std::atomic_flag 1. std::atomic_flag是一个bool类型的原子变量,它有两个状态set和clea ...

  3. 如何用代码设置机器人初始坐标实现 2D Pose Estimate功能

    前言:ROS机器人有时候会遇到极端的情况:比如地面打滑严重,IMU精度差,导致积累误差严重,或是amcl匹配错误,导致机器人定位失败, 这时候如何矫正机器人位置变得非常重要,我的思路是利用相机或是在地 ...

  4. [转帖]SQL Server 10分钟理解游标

    SQL Server 10分钟理解游标 https://www.cnblogs.com/VicLiu/p/11671776.html 概述 游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合 ...

  5. 【05】Saltstack:配置详解

    写在前面的话 上一节迷迷糊糊的说了一下配置管理,这一节主要谈谈我们常见的一些操作如何将他转换成配置文件的形式来实现.这样的好处在于,我们可以一次编写到处使用,不用每次再去编写复杂的命令. 配置回顾 在 ...

  6. 【05】Kubernets:资源清单(控制器 - ReplicaSet)

    写在前面的话 从上一章节开始,我们一直在学习关于自主式 Pod 的资源清单编写, 但是自主式 Pod 存在着一个问题,就是和我们直接 docker run 运行 docker 容器一样.如果我们想以集 ...

  7. plsql developer启动变慢的原因

    导致原因 在plsql developer工具里面有打印的选项,进入打印设置后会调用打印机设置,显示所有已创建的打印机连接.如果当前电脑默认打印机是网络打印机,并且此网络打印机处于不可用状态时,那么p ...

  8. 深入V8引擎-引擎内部类管理解析

    v8的初始化三部曲,前面花了三篇解决了第一步,由于只是生成了一个对象,第二步就是将其嵌入v8中,先看一下三个步骤. // 生成默认Platform对象 std::unique_ptr<v8::P ...

  9. Redis 分析部分功能所解决的问题

    前言:说到缓存,大家都会想到redis,而redis中又有各种眼花缭乱的功能,今天就来看看这些功能能解决的问题. Redis官方简介 Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存 ...

  10. Dictionary<string, Dictionary<string, Person>> dic = new Dictionary<string, Dictionary<string, Person>>();

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace Console ...