Manacher算法,又叫“马拉车”,它可以在时间复杂度和空间复杂度都是O(n)的情况下,求出一个字符串的最长回文串长度。

回文串的基本解法

以每一个点为中心对称点,每次保留最长回文子串的长度,最后得到的就是最长回文子串的长度,但是这样的时间复杂度为O(n^2),并且奇偶回文串是不一样的,比如“aba”的对称中心为“b”,而“abba”的对称中心在两个“b”之间,所以,为了解决这样的问题,可以在每两个字符之间添加一个特殊字符,比如“#”,字符串变成这样“#a#b#b#a#”,求得中间“#”的回文串长度为9,再除2,就得到回文串的长度为4。

基础解法的时间复杂度太高了,所以就有了Manacher算法,他的复杂度为O(n),用起来很方便。

刚开始看马拉车,用了很长时间,只要搞明白原理就能懂了。

下面开始详细讲解Manacher算法

对于奇偶字符串的处理,manacher采用的是填充特殊字符的方法(上文提到过),并且在字符串两端都加入不同的字符,防止越界(因为不同字符一定不是回文串),比如字符串“abbccbba”,增加字符后变成“@#a#b#b#c#c#b#b#a#0”.

重定义字符串代码

重定义字符串的长度为2*n+2。

void getstr() {//重定义字符串int k = 0;str[k++] = '@';//开头加个特殊字符防止越界for (int i = 0; i < len; i++) {str[k++] = '#';str[k++] = s[i];}str[k++] = '#';len = k;str[k] = 0;//字符串尾设置为0,防止越界
}

在重新定义字符串之后,就要开始进行Manacher算法了,先来看一下核心算法。

int manacher() {int mx = 0, id;//mx为最右边,id为中心点int maxx = 0;for (int i = 1; i < len; i++) {if (mx > i) Len[i] = min(mx - i, Len[2 * id - i]);//判断当前点超没超过mxelse Len[i] = 1;//超过了就让他等于1,之后再进行查找while (str[i + Len[i]] == str[i - Len[i]]) Len[i]++;//判断当前点是不是最长回文子串,不断的向右扩展if (Len[i] + i > mx) {//更新mxmx = Len[i] + i;id = i;//更新中间点maxx = max(maxx, Len[i]);//最长回文字串长度}}return (maxx - 1);
}

看上去不是很好理解,下面开始分步讲解

首先对数据进行初始化,再对i进行判断,分为两种情况
第一种情况,i>=mx,i在mx前面,直接让len[i]=1。
第二种情况,i<mx,这时候就又有两种情况了,对len[j]和mx-i进行比较:
(1)len[j]<=mx-i说明i的最右端还在mx里面,如上图所示,只需要让len[i]=len[j]即可。
(2)len[j]>mx说明i的最右端大于mx了,如下图所示,所以我们需要对这两种情况再讨论一下,当Len[j] < mx-i的时候,表示Len[i]的长度可能不会超过mx-i,所以我们就从i的Len[2*id - i]也就是Len[mx-i]的地方开始匹配。当Len[j] > mx - i的时候,说明i位置的子串长度超过了mx,但mx以外的地方还没有遍历到,所以我们就从mx-i也就是mx的位置开始对i匹配。

如果len[i]+i>mx,就对mx进行更新,并且将中间点id更换成i,再通过比较更新最长回文串长度,返回最大值。

Manacher模板代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1e6 + 5;
char s[maxn * 2], str[maxn * 2];
int Len[maxn * 2], len;
void getstr() {//重定义字符串int k = 0;str[k++] = '@';//开头加个特殊字符防止越界for (int i = 0; i < len; i++) {str[k++] = '#';str[k++] = s[i];}str[k++] = '#';len = k;str[k] = 0;//字符串尾设置为0,防止越界
}
int manacher() {int mx = 0, id;//mx为最右边,id为中心点int maxx = 0;for (int i = 1; i < len; i++) {if (mx > i) Len[i] = min(mx - i, Len[2 * id - i]);//判断当前点超没超过mxelse Len[i] = 1;//超过了就让他等于1,之后再进行查找while (str[i + Len[i]] == str[i - Len[i]]) Len[i]++;//判断当前点是不是最长回文子串,不断的向右扩展if (Len[i] + i > mx) {//更新mxmx = Len[i] + i;id = i;//更新中间点maxx = max(maxx, Len[i]);//最长回文字串长度}}return (maxx - 1);
}
int main() {scanf("%s", s);len = strlen(s);getstr();printf("%d\n",manacher());return 0;
}

彻底搞懂马拉车(Manacher)相关推荐

  1. zhs16gbk对应mysql_[Oracle] 彻底搞懂Oracle字符集

    基本概念字符集(Character set):是一个系统支持的所有抽象字符的集合.字符是各种文字和符号的总称,包括各国家文字.标点符号.图形符号.数字等.常见的字符集有ASCII,ZHS16GB231 ...

  2. 面试必备|带你彻底搞懂Python生成器

    2019年人工智能系统学: https://edu.csdn.net/topic/ai30?utm_source=ai100_bw 作者 | Rocky0429 转载自 Python空间(ID:Dev ...

  3. 20分钟教你搞懂Git!

    Git 是最流行的版本管理工具,也是程序员必备的技能之一.本文就来教你 20 分钟搞懂 Git! 以下为译文: 尽管每天你都会用到Git,但也有可能搞不懂它的工作原理.为什么Git可以管理版本?基本命 ...

  4. 搞懂机器学习的常用评价指标!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:陈安东,湖南大学,Datawhale成员 我与评价指标的首次交锋是 ...

  5. 一文搞懂结构体的定义及实际使用

    大家好,我是无际,无实战不理论. 今天给大家讲一下结构体. 大家可能很好奇,为什么这种文章教程泛滥了,我还要拿出来讲. 相信无际的铁粉都知道,我分享的干货和经验出发点是实际产品应用. 脱离产品你所学的 ...

  6. 想要彻底搞懂“异地多活”,看完这篇就够了

    在软件开发领域,「异地多活」是分布式系统架构设计的一座高峰,很多人经常听过它,但很少人理解其中的原理. 异地多活到底是什么?为什么需要异地多活?它到底解决了什么问题?究竟是怎么解决的? 这些疑问,想必 ...

  7. 这一次,你能彻底搞懂 Flink!

    近年来,AI 场景发展得如火如荼,同时其计算规模也越来越大.这也让专注于数据处理的 Flink 有了较大的发展空间.Flink作为在大数据生态里实时处理的一个新框架,在一定程度上也有一定的难度. Fl ...

  8. C语言重点——指针篇(一篇让你完全搞懂指针)

    C语言重点--指针篇(一篇让你完全搞懂指针) 一. 前言 C语言是比较偏底层的语言,为什么他比较偏底层,就是因为他的很多操作都是直接针对内存操作的. 这篇我们就来讲解C语言的一大特点,也是难点,指针和 ...

  9. C++搞懂深拷贝初始化=与赋值(运算符重载)=的区别

    C++搞懂深拷贝初始化=与赋值(运算符重载)=的区别 C++构造函数用=与()不完全一样,注意使用=时c++中临时变量不能作为非const的引用参数,不论是=运算符重载还是构造函数,否则可能出现以下错 ...

最新文章

  1. 梦境交互:做个现代灵媒,考虑一下?
  2. x86 下制作 ARM Docker 镜像,Docker Hub、Travis 自动构建 qemu-user-static
  3. Have a tea -(极客大挑战(SMC,fork
  4. showModalDialog和showModelessDialog缓存问题,参数详解,
  5. 汇编入门学习笔记 (十二)—— int指令、port
  6. 本机连接opc server有部分数据不刷新_实时数据库PI在企业MES系统中的应用
  7. python 音速_中国大学MOOC的APP(慕课)2021用Python玩转数据章节答案
  8. archman linux教程,Archman GNU/Linux 2020-01 发布,基于Arch的Xfce桌面发行版
  9. 渗透测试-内网横向MS-17010利用方法总结
  10. CentOS 某服务器搭建问题收集
  11. Python自学(三)
  12. VS Code:推荐插件 - HTML格式化(包括JS、CSS)
  13. 数据库基本知识掌握(一)
  14. word文档中的毕业论文的页眉与页脚设置
  15. Kotlin Symbol Processing(KSP)使用初体验
  16. FL Studio 21最新中文版安装教程
  17. 认养一头牛冲刺A股:拟募资18.5亿 徐晓波持股近40%
  18. 因计算机丢失d3dx9-30,win10 64位纯净版运行仙剑5提示缺少d3dx9_30.dll的修复方法
  19. remote call
  20. jpa mysql timestamp_Java JPA设置默认值、Timestamp设置、自动获取时间

热门文章

  1. XTransfer外贸收款账户和传统收款账户的区别?
  2. IOCP之AcceptEx的问题(1)
  3. http://www.snap.com/
  4. 中国健康、医疗大数据中心盘点(持续更新)
  5. 绿色环保网站管理系统mysql
  6. python 并发下载器
  7. 【Hadoop--04】Hadoop读文件
  8. 自动化测试解决了什么问题,看看这些行业大牛给出的回答
  9. Android自定义view刷新方法
  10. dell服务器显示屏不亮,戴尔台式机屏幕不亮的解决方法