「字符串」Manacher算法(马拉车)/ LeetCode 05(C++)

马拉车算法(C/C++) 是一种用于在字符串中查找最长回文子串的线性时间复杂度算法。该算法由Udi Manacher在1980年代提出,因此得名。它的核心思想是利用已知的回文信息来减少不必要的比较,从而提高效率。 阅读详情

目录

概述

思路

算法过程

复杂度

Code


概述

今天我们来讲一个巧妙地以O(n)时间复杂度求解字符串最大回文串的算法。

LeetCode 05:

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

思路

我们回想中心扩散法:抵达一个字符s[i],向他的身前和身后同时遍历

while(s[i+r]==s[i-r])r++,直到不再相等位置。

某字符处的中心扩散完毕后,其实已经将它身前身后的字符段落都搜索过了,那么如果我们搜索其后的字符能够利用这一点,能否避免不必要的搜索来达到线性时间复杂度O(n)呢?

我们不妨先研究比较简单的一种情况:回文子串只有一个回文中心,是一个奇字符串(后续我们可以用一些方法将奇偶字符串全部处理成奇字符串)

观察这段字符:

           --------x--------
             --a--     
char[i]: f t b a b x b a b t g
     i : 0 1 2 3 4 5 6 7 8 9 10
 Now i :       &   c   |

当我们来到char[7]='a'位置时(在图中用‘|’来表示),我们发现他被此前的以'x'为中心的当前最长回文串覆盖住了。

这表明我们可以用此处的以'x'为中心的对称点来快速判断而不需要进行暴力扩散。

回文中心:我们将'x'所在位置称为c,这是我们的回文中心。

半径数组r[i]:记录每个点的回文半径(回文半径=本身+扩散距离,如r[c]=5)容易发现i=7的对称点ii=c-(i-r[c])=3。(在图中用‘&’来表示)

我们发现ii的回文长度被c的回文长度完全覆盖,这意味着i的回文长度和ii是相等的(两侧对称),那么直接r[i]=r[ii]即可快速得到i的回文长度。

(思考:如果i的回文长度比ii更长的话,那么当初利用中心扩散判断c的回文时一定不是r[c]=5)

在进行遍历的同时维护中心c,如果某字符在c的屋檐下,那么可以利用回文串的对称性质来避免重复的暴力扩散(毕竟为了得到c的回文长度时我们进行过暴力扩散了),这就是Manacher算法的思想。

只在得到中心c时进行暴力扩散,后续的字符通过c来判断,这样我们就保证了c身前身后的字符只被遍历了一次,因此时间复杂度是O(n)。


算法过程

我们有两个工作要做:一是处理字符串使其称为奇字符串(只有一个中心字符);二是判断i的对称位置ii的三种情况

首先对字符串进行插值处理:

string ss="#";
for(int i=0;i<s.size();i++){
ss.push_back(s[i]);
ss.push_back('#');
}
//s="abacc"则ss="#a#b#a#c#c#"

原字符串的任意回文子串长度为len,新字符串的长度为2*len+1,必然是奇字符串。
这一步的时间复杂度为O(n),有限个线性时间复杂度加和仍是线性的。

接下来开始判断三种情况:

  1. i=7的对称点ii=3的回文半径被r[c]完全覆盖
               --------x--------
                 --a--     
    char[i]: f t b a b x b a b t g
         i : 0 1 2 3 4 5 6 7 8 9 10
     Now i :           c   |
    

    此时r[i]=r[ii],直接continue循环

  2.  i=7的对称点ii=3的回文半径超出r[c]
               --------x--------
             ------a------     
    char[i]: b x b a b x b a b x g
         i : 0 1 2 3 4 5 6 7 8 9 10
     Now i :           c   |

    此时对r[ii]进行截断,r[i]=ii-(c-r[c])。
    这是因为如果r[i]==r[ii],当初暴力扩散r[c]的时候得到的结果不可能使r[ii]超出r[c],r[i]==r[ii]时得到的r[c]长度即为情况1)

  3. i=7的对称点ii=3的回文半径恰好压线
               --------x--------
               ----a----
                     ------a------     
    char[i]: f x b a b x b a b x b
         i : 0 1 2 3 4 5 6 7 8 9 10
     Now i :           c   |

    此时我们只能知道r[i]至少等于r[ii],此后应进行暴力扩散

最后,如果我们得到的新回文半径比r[c]长,那么应该令c=i来确保c的r[c]的全局最大性。
至于i>c+r[c]-1?(i不在最长回文串覆盖下)直接暴力扩散就好了。

得到结果后利用string::substr(int pos,int n)(从pos开始的n个字符)方法截取以c为中心的全局最长回文串,过滤掉插值字符'#'后输出答案即可。


复杂度

时间复杂度: O(n)

空间复杂度: O(n)


Code

class Solution {
public:
    string longestPalindrome(string s) {
        string ss="#";
        for(int i=0;i<s.size();i++){ss.push_back(s[i]);ss.push_back('#');}//处理字符串
        int c=0,r[2001]={1,};
        for(int i=1;i<ss.size();i++){
            int j=1;//用j临时表示当前得到的回文半径
            if(i<=c+r[c]-1){//i在当前最长回文串中
               int ii=c-(i-c);//↓以下为讨论三种情况
               if(ii-r[ii]>c-r[c]){r[i]=r[ii];continue;}//r[ii]被r[c]完全覆盖
               else if(ii-r[ii]<c-r[c]){r[i]=ii-(c-r[c]);continue;}//r[ii]超出r[c]
               else j=r[ii];//r[ii]压线
            }
            //↓需要暴力扩散:i不在回文串中或r[ii]压线
            while(i+j<ss.size()&&i-j>=0&&ss[i+j]==ss[i-j])j++;
            r[i]=j;
            if(r[i]>=r[c])c=i;//更新c保证其全局最大
        }
        //↓生成答案,ans保存答案,ANS保存未过滤‘#’的临时字符串
        string ans="",ANS=ss.substr(c-r[c]+1,2*r[c]-1);
        for(int i=0;i<ANS.size();i++)
           if(ANS[i]!='#')ans.push_back(ANS[i]);
        return ans;
    }
};

汽车级智能栅极驱动器深度解析 | 连载01:DRV871x-Q1系列产品架构与核心特性 集成度:单芯片集成多通道驱动器、电源管理、电流检测智能化:自适应控制算法,减少外部元件可靠性:多重保护机制,满足汽车级要求灵活性:SPI和硬件两种接口,适应不同应用需求。 阅读详情

相关推荐

Ubuntu22.04下,用Fast-LIVO2+3DGS重建桌面小物件:从点云到高清模型的保姆级避坑实录

本文详细介绍了在Ubuntu22.04环境下,使用Fast-LIVO2与3DGS技术进行桌面小物件三维重建的完整流程。从环境配置、数据采集到点云-图像对齐和3DGS训练,提供了针对小物件优化的参数设置和避坑指南,帮助用户实现媲美商业扫描仪的高清模型重建效果。

weixin_30897233的博客 399

C++实现Manacher算法【马拉车】

最近研究了一下Manacher算法,本人非科班出身,参考很多大牛资料,最终终于搞明白了,感觉甚是不易,遂做此笔记,整理很多次,思路感觉还算清晰,希望对大家有所帮助!!!纯手工画图,感觉不错的朋友,点个赞哟@_@ 主要功能:解决最长回文子串的问题[给定一个字符串,求解其最长回文子串的长度] 1、大体思路阐述 给定一个字符串str = “abbc”,求解其最长回文子串的长度??? 对原来的字符...

你是猴子请来的精兵吗??? 1230

【STM32Cube HAL】输入捕获(六)——脉宽测量

1

HAHAHA 4907

C++马拉车(Manacher)算法

文章目录功能马拉车算法初始化 功能 马拉车算法(Manacher’s Algorithm):用O(n)O(n)O(n)的时间得到一个字符串中,以每个字符为中心的最长回文的长度。 马拉车算法 初始化 ...

ixRic 5885

VisionMaster 4.2.0安装

按照顺序安装。

XuXing_java的专栏 3791

VirtualBox虚拟机上ubuntu系统安装问题记:显示画面太小、启动就异常退出等

报错:Failed to load R0 module D:/VMMR0.r0: The path is not clean of leading double slashes: ‘D:/VMMR0.r0’ (VERR_SUPLIB_PATH_NOT_CLEAN).解决方法特别简单,就是安装VIrtualBox的时候不要安装在CDE等盘根目录下。首先VirtualBox的下载安装过程是比较简单的,此处就不赘述了。然后E盘下新建个目录,安装到这个目录下就可解决。

qq_42595610的博客 2826

C++Manacher(马拉车)算法

Manacher算法以独特的预处理方式和回文数组出名,以添加特殊字符处理字符串奇偶,以回文半径数组处理回文串。算法复杂度占优,值得入手。

2401_90042730的博客 1323

MAX30102心率血样模块在STM32F103芯片的程序说明

我希望你已经安装好了Keil MDK5这个软件,也安装了M3内核,可以编译一些STM32F103的一些项目下载程序后步骤: 1-按照下图找到IIC.uvprojx并打开(途中唯一绿色那个图标) 2-编译一次 3-确保0错误,0警告,下图所示 4-点击目标选项,然后找到STM32F103C8,再点debug–CMSIS****(我实际用的JTAG,用不了,选择这个CMSIS****即可)下图所示 5-下图所示,看看你的串口找到了没,找到了就点左下角的OK 6-按图上传到开发板 7-MAX30102接线方法

weixin_51357422的博客 5801

C++马拉车算法

P[i]:表示以预处理后字符串第i个字符为中心的最长回文半径(不包括自身)。核心变量C:当前回文中心R:当前回文右边界(最右扩展位置)Manacher算法通过巧妙的预处理和对称性利用,将最长回文子串的求解优化至线性时间,展现了算法设计中的“空间换时间”与“分治思想”。尽管其实现细节较为复杂,但掌握后能显著提升字符串处理效率。未来可进一步探索其在多维数据或并行计算中的扩展应用。

C++发展史系列已完结,这段时间将会迎来系列作品——C++STL系列,敬请期待。作者邮箱:ljq20110324@outlook.com 781

Python 实战:爬取高德地图交通数据(路况拥堵指数分析)

高德地图是由高德软件有限公司开发的一款地图导航产品,提供详细的地图浏览、路线规划、实时路况、公共交通查询等功能。高德地图拥有庞大的用户群体和海量的交通数据,这些数据对于交通管理、城市规划、出行服务等领域具有重要的价值。通过对高德地图交通数据的分析,我们可以了解城市交通的运行状况,识别拥堵路段,预测交通流量,为交通管理部门和出行者提供决策支持。

yansideyucsdn的博客 2685

数字电路逻辑与设计实验一 门电路逻辑功能及测试

(1)选二输入四异或门电路 74LS86,按图 1-8 接线,输入端 1、2、4、5 接逻辑开 关(S1~S4),输出端 A、B、Y 接电平显示发光二极管.用六反相器(非门)按图 1-11 接线,输入 80KHz 连续脉冲,用双踪示波器测输入, 输出相位差,计算每个门的平均传输延迟时间的 tpd 值。测试不同的输入组合:对门电路进行全面的测试,尝试不同的输入组合,包括各种可能的逻辑状态。检查门电路的输入:确认门电路的输入是否正确,并且输入信号的电平符合门电路的规格要求。确保输入信号的稳定性和准确性。

欢迎交流学习心得 2万+

马年“码”上发力:用Manacher“马拉车”算法,拉平最长回文难题

今年是马年, 我来分享一个与 “马” 有关的算法, Manacher(马拉车)。 前言 Manacher(马拉车)算法 问题: 1.相关概念引入 2.中心扩展算法 算法原理 预处理 3.Manacher算法 概念引入 分类讨论(核心) 4.算法模板 结尾

燃于AC之乐的博客 1407

03、ZigBee 开发教程之进阶篇—CC2530无线传输质量检测

文章目录1、Packet Error Rate Tester(包错误率测试)理论分析1.1、工作流程1.2、流程图1.3、丢包、PER、RSSI计算方法2、实验详解2.1、实验目的2.2、实验设备2.3、实验现象2.4、源码分析2.5、实验步骤及现象 1、Packet Error Rate Tester(包错误率测试)理论分析 1.1、工作流程 Packet Error Rate Tester(包错误率测试) 1、启动 板载外设、射频IO、系统时钟、中断等初始化(halBoardInit();); Bas

嵌入式羊圈 1538

字符串匹配—— 28、686、459、214 ※马拉车 BF KMP算法

新手刷题自用记录(新学三个算法 今天也是写得有点鼠了

Utgnryk的博客 1836

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Manacher(马拉车)算法详解、证明和练习题

给你一个字符串,让你在末尾添加最少数量的字符,使得添加后的字符串为回文串 关于这道题,可以用Manacher算法的思想来做。 首先找到以给出的字符串最后一个字符结尾的最长回文串,然后从头开始,遇见最长回文串的开头就停止,将这段字串逆序贴在整个字符串的末尾就是答案,举个例子: 假设给出的字符串是:abcxyzfzyx,可以看出以最后一个字符结尾的最长回文串是xyzfzyx,然后从字符串的头开始遍历,直到x的前一个位置,最后遍历得到的子串为abc,将abc逆序为cba贴在给出的字符串后面即为答案:abcxyz

qq_39579087的博客 938

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

LeetCode5. Longest Palindromic Substring(马拉车算法 Manacher Algorithm)

一、问题描述 Given a string s, find the longest palindromic substring *(最长回文字符串)*in s. You may assume that the maximum length of s is 1000. Example: Input: “babad” Output: “bab” Note: “aba” is also a v...

天天向上 920

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

leetcode-5.最长回文子串-manacher

Question:给你一个字符串 s,找到 s 中最长的回文子串。 leetcode-5 该题使用马拉车算法解时间复杂度和空间复杂度均为O(n)O(n)O(n) manacher思想介绍: 一、(center) CCC为回文串对称中心坐标 二、(radius) R[C]R [C]R[C] 以C为对称中心的回文串半径 三、(iterator) III 对称中心在R[C]范围内,且I>CI>CI>C的回文串对称中心坐标 四、(Point) PPP以C为中心,回文串结束的下标 下

qq_39047461的博客 227

Manacher马拉车算法--求最大回文子串

转载: 作者:windliang 链接:链接 来源:力扣(LeetCode) 看了这位大佬的题解明白了马拉车 求原字符串下标 用 P 的下标 i 减去 P [ i ],再除以 2,就是原字符串的开头下标了。 例如我们找到 P[ i ] 的最大值为 5,也就是回文串的最大长度是 5,对应的下标是 6,所以原字符串的开头下标是(6 - 5 )/ 2 = 0。所以我们只需要返回原字符串的第 0 到 第(5 - 1)位就可以了。 求每个 P [ i ] 接下来是算法的关键了,它充分利用了回文串的对称性。 我们用

时间,抓起了就是黄金,虚度了就是流水 237

leetcode214. 最短回文串

214. 最短回文串 难度困难114 给定一个字符串s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例1: 输入: "aacecaaa" 输出: "aaacecaaa" 示例 2: 输入: "abcd" 输出: "dcbabcd" 思路:马拉车求出以0开头的最大回文串,然后在前面添加后面字符串的翻转即可。 傻子都能看懂的马...

少说,多做。 2922

LeetCode 5 最长回文子串 Manacher(马拉车)算法 (C语言)

题目: 给你一个字符串 s,找到 s 中最长的回文子串。 示例1: 输入:s = “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。 示例2: 输入:s = “cbbd” 输出:“bb” 示例3: 输入:s = “a” 输出:“a” 示例4: 输入:s = “ac” 输出:“a” 提示: 1 <= s.length <= 1000 s 仅由数字和英文字母(大写和/或小写)组成 解题代码: // 这个函数都能看懂 char * strSretreat

qq_43623492的博客 1242

Manacher算法实战:从原理到代码实现的全解析

本文深入解析了Manacher算法(马拉车算法)的核心原理与代码实现。通过插入特殊字符统一处理奇偶回文,并利用对称性避免重复计算,该算法能以O(n)时间复杂度高效求解最长回文子串问题。文章提供了Python和C++的详细实现代码,并探讨了其在统计回文子串数量等场景的进阶应用。

sugar的博客 896

Manacher算法/O(n)时间复杂度求字符串中最长回文子字串算法

Manacher算法/O(n)时间复杂度求字符串中最长回文子字串算法 刷leetcode的5.Longest Palindromic Substring时被虐的要死要活的……找了一下才发现历史上已有存在的最优算法,manacher(马拉车)算法。 但网上大多数博客都晦涩难懂,在此用简单的语言解释、记录一下。 java代码实现在文末。 规则: 1、最长回文子串的长度是半径减1...

wu2007369的博客 350

删去字符串中的子串_leetcode 5 最长回文子串(c++)

第一种直接利用动态规划,主要是写好状态转移方程,第二种是中心扩展法,第三种是manacher马拉车(经评论区提醒后添加)。### 题目给定一个字符串 s,找到 s 中最长的回文子串。你可以假设s的最大长度为1000。示例 1:输入: "babad"输出: "bab"注意: "aba" 也是一个有效答案。示例 2:输入: "cbbd"输出: "bb"### 思路主要是要找好动态转移方程,定义一个长...

weixin_36470210的博客 259

LeetCode高频题5:最长回文子串,利用马拉车manacher算加速

1)马拉车manacher算法的核心在利用i位置对称位置2c-i的回文半径,加速求得i的回文半径,每次把最大回文中心更新给maxC,回文半径更新给pArr,最大回文右边界回文给R 2)最后马拉车算法的maxC,需要除2对应映射给原串s,然后求start和end,用substring截取即可。 3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。...

weixin_46838716的博客 529

最长回文串 马拉车算法 C++

最长回文串 LeetCode 5.最长回文串 给你一个字符串 s,找到 s 中最长的回文子串。 示例 1: 输入:s = “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。 示例 2: 输入:s = “cbbd” 输出:“bb” 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 解法一:暴力枚举 把字符串中所有是回文串的子串都挨个遍历一遍,记录下最长回文串的长度和起始

qq_33894666的博客 394

LeetCode5.最长回文子串————Manacher算法

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。 示例 1: 输入: “babad” 输出: “bab” 注意: &amp;amp;quot;aba&amp;amp;quot;也是一个有效答案。 示例 2: 输入: “cbbd” 输出: “bb” 方法一: 动态规划,O(n^2) i 为做指针,j 为右指针。 dp[ i ][ j ]指:从i到j位置组成的字串是否回文,回文则1,否则0。 若str[ i...

一只热爱游戏的猫咪 557
上一篇: 力扣第19题:删除链表的倒数第N个结点 记忆化存取(C++)
下一篇: 力扣第70题:爬楼梯 动态规划DP入门(C++)
Daking-
博客等级 码龄3年 912粉丝 70原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值