马拉车算法(C/C++)

#1024程序员节 | 征文#

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

算法步骤

  1. 预处理字符串: 为了处理奇数长度和偶数长度的回文串,算法首先对输入字符串进行预处理。在每个字符之间插入一个特殊字符(通常是#),并在字符串的开头和结尾也各插入一个。这样做的目的是为了让每个字符都有一个唯一的中心位置。

  2. 初始化变量

    • p[]:一个数组,用于存储每个位置的回文半径。
    • C:当前考虑的中心位置。
    • R:当前考虑的右端点,即以C为中心的回文串的最右端。
  3. 遍历字符串: 对于预处理后的字符串中的每个位置i,算法尝试找到以i为中心的回文串的半径。这个过程分为两步:

    • 利用已知的回文信息:如果i在当前考虑的回文串内(即i < R),则可以利用对称位置的回文半径来减少比较次数。
    • 扩展回文串:如果i不在当前考虑的回文串内,或者需要进一步扩展回文串,算法会尝试扩展以i为中心的回文串,直到无法进一步扩展。
  4. 更新最大回文串: 在遍历过程中,如果找到的回文串半径大于之前记录的最大半径,则更新最大回文串的起始位置和半径。

  5. 提取最长回文子串: 遍历完成后,根据记录的最大半径和起始位置,从原始字符串中提取最长的回文子串。


算法详解

  • 中心扩展思想:马拉车算法利用了中心扩展的思想,即以每个字符为中心,向两边扩展,直到无法形成回文串为止。这种方法可以避免重复比较相同的字符对。

  • 利用对称性:算法利用了回文串的对称性,即如果以i为中心的回文串已知,那么以2*C - i为中心的回文串的半径至少与以C为中心的回文串的半径相同。这里C是当前考虑的中心位置。

  • 动态规划:虽然马拉车算法不是传统意义上的动态规划算法,但它的思想与动态规划类似,即利用之前计算的结果来简化当前的计算。


复杂度分析

  • 时间复杂度:O(n),其中n是输入字符串的长度。这是因为每个位置的回文半径只计算一次。
  • 空间复杂度:O(n),用于存储回文半径的数组。

代码实现:

#include <iostream>
#include <vector>
#include <string>
using namespace std;string manacher(const string& s) {if (s.empty()) return s;// 预处理字符串,插入特殊字符string t = "#";for (char c : s) {t += c;t += "#";}int n = t.length();vector<int> p(n, 0);int C = 0, R = 0; // C为当前回文的中心,R为当前回文的右边界int maxLen = 0, centerIndex = 0;for (int i = 1; i < n; i++) {if (i < R) {int mirror = 2 * C - i;p[i] = min(R - i, p[mirror]);}int left = i - p[i], right = i + p[i];while (left >= 1 && right < n - 1 && t[left - 1] == t[right + 1]) {p[i]++;left--;right++;}if (i + p[i] > R) {C = i;R = i + p[i];}if (p[i] > maxLen) {maxLen = p[i];centerIndex = i;}}// 从预处理的字符串中提取最长回文子串int start = (centerIndex - maxLen) / 2;return s.substr(start, maxLen - 1); // 减1是因为预处理字符串中插入了特殊字符
}int main() {string s;cin >> s;cout << manacher(s) << endl;return 0;
}


应用实例:

在LeetCode上的题目“5. Longest Palindromic Substring”就是一个典型的应用实例,要求找出给定字符串中的最长回文子串。马拉车算法可以应用于生物信息学中DNA序列的回文结构分析,以及文本处理中的回文检测等场景。该算法也可以用于解决其他与回文相关的问题,如找出所有回文子串、判断回文对等。

算法实现部分:
string manacher(string s) {string t = "#";for (char c : s) {t += c;t += "#";}vector<int> p(t.size(), 0);int C = 0, R = 0;int maxLen = 0, centerIndex = 0;for (int i = 1; i < t.size(); i++) {if (i < R) p[i] = min(p[2 * C - i], R - i);else p[i] = 1;while (t[i + p[i]] == t[i - p[i]]) p[i]++;if (i + p[i] > R) {C = i;R = i + p[i];}if (p[i] > maxLen) {maxLen = p[i];centerIndex = i;}}int start = (centerIndex - maxLen) / 2;return s.substr(start, maxLen - 1);
}

马拉车算法是解决最长回文子串问题的有效方法,其线性时间复杂度使其在处理大规模数据时具有明显优势。文章到此为止感谢大家的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454274.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】-权限

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;深入代码世界&#xff0c;了解掌握 Linux 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ​ 一、权限的概念 在Linux 中&…

软件测试与软件缺陷的基础知识

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

技术面没过,竟然是因为我没用过Pytest框架?

想象一下&#xff0c;你在一次技术面试中满怀信心&#xff0c;答完所有问题&#xff0c;结果却被告知没通过&#xff0c;原因竟然是——你没用过Pytest框架&#xff01;是的&#xff0c;在当今软件测试的世界里&#xff0c;Pytest已经成为了许多公司的“必备”技能。 那么问题…

数据库表的创建

运用的环境是pychram python3.11.4 创建一个表需要用到以下语法 注释已经写清楚各种语法的含义&#xff0c;记住缩进是你程序运行的关键&#xff0c;因为程序是看你的缩进来判断你的运行逻辑&#xff0c;像我这个就是缩进不合理导致的报错 那么今天分享就到这里&#xff0c;谢…

QScrollBar滑动条控件

人机验证简化版案例 //设置垂直滑动条的范围是0-100ui->verticalScrollBar->setRange(0,100);ui->horizontalScrollBar->setRange(0,100);//设置初始数值ui->verticalScrollBar->setValue(50);//void valueChanged(int value);connect(ui->verticalScroll…

uniapp修改input中placeholder样式

Uniapp官方提供了两种修改的属性方法&#xff0c;但经过测试&#xff0c;只有 placeholder-class 属性能够生效 <input placeholder"请输入手机验证码" placeholder-class"input-placeholder"/><!-- css --> <style lang"scss" s…

基于图像拼接开题报告

选题的背景与意义 在日常生活中&#xff0c;使用普通相机获取宽视野的场景图像时&#xff0c;必须通过调节相机的焦距才可以提取完整的场景。由于相机的分辨率有限&#xff0c;拍摄场景越大&#xff0c;得到的图像分辨率就越低&#xff0c;因此只能通过缩放相机镜头减小拍摄的…

VSCode按ctrl与鼠标左键无法实现跳转的解决办法

vscode编译环境老是出问题&#xff0c;下面介绍两种解决方法 需要提前配置好代码编译需要的库以及编译器位置等等。 ctrlshiftp,输入 >C/C配置&#xff08;JSON&#xff09; 打开生成的c_cpp_properties.json {"configurations": [{"name": "Li…

NSSCTF-WEB-easy_eval

目录 前言 正文 思路 序列化构造 后渗透 思路点1:Redis 思路2:蚁剑插件绕过disable_functinons 结尾 作者的其他文章 前言 说是easy,实际很difficult 正文 思路 <?php class A{public $code "";function __call($method,$args){//最后执行命令eval($th…

github加速 DevSidecar 1.8.8

DevSidecar 1.8.8 更多配置请参考&#xff1a;github开源

impdp+remap_schema导入后登录报ORA-01017: Invalid Username/password

环境说明&#xff1a;有个11.2.0.4的rac数据库&#xff0c;现需要把USR_OA克隆一份出来做测试&#xff0c;新用户名是TEST_OA&#xff0c;直接是expdp导出用户&#xff0c;再用impdpremap_schema生成TEST_OA&#xff0c; 业务人员使用PLSQL(版本12.0.1.1814) 登录TEST_OA时总…

GJS-WCP

不懂的就问&#xff0c;但我也是二把手......哭死 web GJS-ezssti 很常规的ssti模板注入&#xff0c;只过滤了"/","flag"。 过滤了/,flag 可以利用bash的特性绕过&#xff0c;如字符串截取&#xff0c;环境变量等等。payload1: {{url_for.__globals__[…

[项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 | scp

目录 一、前言 二、项目的相关背景 三、搜索引擎的宏观原理 四、搜索引擎技术栈和项目环境 五、正排索引 VS 倒排索引--原理 正排索引 分词 倒排索引 六、编写数据去除标签和数据清洗模块 Parser 1.数据准备 parser 编码 1.枚举文件 EnumFile 2.去标签ParseHtml(…

文件处理新纪元:微信小程序的‘快递员’与‘整理师’

嗨&#xff0c;我是中二青年阿佑&#xff0c;今天阿佑将带领大家如何通过巧妙的文件处理功能&#xff0c;让用户体验从‘杂乱无章’到‘井井有条’的转变&#xff01; 文章目录 微信小程序的文件处理文件上传&#xff1a;小程序的“快递服务”文件下载&#xff1a;小程序的“超…

学习threejs,拉伸几何体THREE.TubeGeometry管道

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️拉伸几何体THREE.TubeGeome…

Git的原理和使用(六)

本文主要讲解企业级开发模型 1. 引入 交付软件的流程&#xff1a;开发->测试->发布上线 上面三个过程可以详细划分为一下过程&#xff1a;规划、编码、构建、测试、发 布、部署和维护 最初&#xff0c;程序⽐较简单&#xff0c;⼯作量不⼤&#xff0c;程序员⼀个⼈可以完…

Imagic: Text-Based Real Image Editing with Diffusion Models

https://openaccess.thecvf.com/content/CVPR2023/papers/Kawar_Imagic_Text-Based_Real_Image_Editing_With_Diffusion_Models_CVPR_2023_paper.pdfhttps://imagic-editing.github.io/ 问题引入 针对的是text based image editing问题&#xff0c;可以解决non rigid edit&am…

【软件安装与配置】 vue

1. 安装 Node.js Vue.js 项目通常依赖于 Node.js 环境来进行开发&#xff0c;可以从 Node.js 官方网站 下载并安装稳定版本。安装 Node.js 后&#xff0c;npm&#xff08;Node 包管理器&#xff09;也会自动安装。 2. 使用 Vue CLI 安装 Vue.js Vue CLI 是一个用于快速搭建 Vu…

柔性数组的使用

//柔性数组的使用 #include<stdio.h> #include<stdlib.h> #include<errno.h> struct s {int i;int a[]; }; int main() {struct s* ps (struct s*)malloc(sizeof(struct s) 20 * sizeof(int));if (ps NULL){perror("malloc");return 1;}//使用这…

用.NET开发跨平台应用程序采用 Avalonia 与MAUI如何选择

Avalonia是一个强大的框架&#xff0c;使开发人员能够使用.NET创建跨平台应用程序。它使用自己的渲染引擎绘制UI控件&#xff0c;确保在Windows、macOS、Linux、Android、iOS和WebAssembly等不同平台上具有一致的外观和行为。这意味着开发人员可以共享他们的UI代码&#xff0c;…