【字符串】马拉车(Manacher)算法

本篇文章参考:比较易懂的 Manacher(马拉车)算法配图详解

马拉车算法可以求出一个字符串中的最长回文子串,时间复杂度 O ( n ) O(n) O(n)

因为字符串长度的奇偶性,回文子串的中心可能是一个字符,也可能是两个字符中间的位置,所以为了解决这个问题,我们在每两个字符之间加一个 # ,开头再加一个 $ 防止越界

比如说:

abcd 变成 $#a#b#c#d#

接下来是后文需要的一些定义:

  • c 表示当前已经计算过的最靠右的回文子串的中心点的下标
  • m 表示以 c 为中心的回文子串的右端点下标
  • p[i] 表示以 s[i] 为中心的回文子串的半径(包括自身)

对于以每一个位置为中心点的时候单独计算,复杂度很大,马拉车可以对其进行很好地优化

目前的难点就是怎么计算 p[i]

在这里插入图片描述

看上面这张图,我们当前需要计算 p[i],我们可以去找 i 关于 c 的对称点(记为 j),因为我们是从左往右计算的,所以 p[j] 已经计算过了,如果以 j 为中心的回文子串在以 c 为中心的回文子串中时,我们可以直接把 p[j] 赋给 p[i]

当然会出现一些特殊情况:

  • 如果 p[j] + i > m,如下图所示,以 c 为中心的回文子串包不住,我们就更新 p[i] = m - i (先只更新确定的部分)
    在这里插入图片描述
  • 如果 i 在 m 右侧,如下图所示,更新 p[i] = 1
    在这里插入图片描述

上面的情况都只能得到半成品的 p[i],所以需要对 s[i] 进行中心扩展,得到最终的 p[i]

如果最终的 p[i] + i > m 此时已经有比以 c 为中心的回文子串更靠右的回文子串了,就把 c = i m = p[i] + 1

求完 p[i] 后算法结束

求最长回文子串板子

string Manacher(string s)
{int sl = s.size(); // 原字符串长度if (sl == 0 || sl == 1) return s;// 构建新串string ns = "$#";for (int i = 0; i < sl; i ++ ){ns += s[i];ns += '#';}int len = ns.size();int c = 0; // 最靠右的回文子串的中心点下标int m = 0; // 最靠右的回文子串的右端点下标int pos = 0; // 最长回文子串的中心点int maxlen = 0; // 最长回文子串的半径(不包括中心点)(新字符串中)vector<int> p(len); // p[i]表示以i为中心点的回文子串的半径(包括i)for (int i = 1; i < len; i ++ ){if (i < m) p[i] = min(p[c - (i - c)], m - i + 1); // c-(i-c)是i关于c的对称点 当前情况表示i在目前最靠右侧的回文子串中else p[i] = 1 + (ns[i] != '#'); // 当前不是#的话 其两侧就是# 所以半径可以加1if (i - p[i] >= 0 && i + p[i] < ns.size())while (ns[i - p[i]] == ns[i + p[i]]) p[i] ++ ; // 对半成品的i位置进行中心扩散if (i + p[i] - 1 > m) // 产生了比以c为中心时更靠右的回文子串{c = i;m = i + p[i] - 1;}if (p[i] - 1 > maxlen) // 更新最长回文子串{maxlen = p[i] - 1;pos = i;}}string ans = "";char tmp;for (int i = 0; i < 2 * maxlen * 1; i ++ ) // 遍历最长字串的每个位置 得出原字符串中的最长字串{tmp = ns[pos - (maxlen - 1) + i];if (tmp != '#') ans += tmp;}return ans;
}

求最长前缀or后缀回文子串板子

string Manacher(string s)
{int sl = s.size(); // 原字符串长度if (sl == 0 || sl == 1) return s;// 构建新串string ns = "$#";for (int i = 0; i < sl; i ++ ){ns += s[i];ns += '#';}int len = ns.size();int c = 0; // 最靠右的回文子串的中心点下标int m = 0; // 最靠右的回文子串的右端点下标int pos = 0; // 最长回文子串的中心点int maxlen = 0; // 最长回文子串的半径(不包括中心点)(新字符串中)// int flag; // 可以用这个标记是前缀回文子串最长还是后缀回文子串最长vector<int> p(len); // p[i]表示以i为中心点的回文子串的半径(包括i)for (int i = 1; i < len; i ++ ){if (i < m) p[i] = min(p[c - (i - c)], m - i + 1); // c-(i-c)是i关于c的对称点 当前情况表示i在目前最靠右侧的回文子串中else p[i] = 1 + (ns[i] != '#'); // 当前不是#的话 其两侧就是# 所以半径可以加1if (i - p[i] >= 0 && i + p[i] < ns.size())while (ns[i - p[i]] == ns[i + p[i]]) p[i] ++ ; // 对半成品的i位置进行中心扩散if (i + p[i] - 1 > m) // 产生了比以c为中心时更靠右的回文子串{c = i;m = i + p[i] - 1;}if (p[i] == i && maxlen < p[i]) // 最长前缀回文子串{maxlen = p[i] - 1;pos = i;// flag = 1;}if (p[i] + i == len && maxlen < p[i]) // 最长后缀回文子串{maxlen = p[i] - 1;pos = i;// flag = 2;}}string ans = "";char tmp;for (int i = 0; i < 2 * maxlen * 1; i ++ ) // 遍历最长字串的每个位置 得出原字符串中的最长字串{tmp = ns[pos - (maxlen - 1) + i];if (tmp != '#') ans += tmp;}return ans;
}

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

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

相关文章

uniapp聊天记录本地存储(详细易懂)

目录 目录 1、通过websocket拿取数据 2、获取聊天数据 3、聊天信息存储 、更新 4、读取聊天记录 5、发送信息&#xff0c;信息获取 6、最终效果 1.聊天信息的存储格式 2、样式效果 写聊天项目&#xff0c;使用到了本地存储。需要把聊天信息保存在本地&#xff0c;实时获…

GPT对话知识库——ARM-Cortex架构分为哪几个系列?每个系列有几种工作模式?各种工作模式之间的定义和区别?每种架构不同的特点和应用需求?

提问模型&#xff1a;GPT-4-TURBO-PREVIEW 提问时间&#xff1a;2024.03.02 1&#xff0c;问&#xff1a; Cortex-M系列有几种工作模式 1&#xff0c;答&#xff1a; Cortex-M系列微控制器是ARM公司开发的一类低功耗、高性能的32位微处理器&#xff0c;广泛应用于嵌入式系统中…

Centos7使用man查找命令时,报错No manual entry for xxxx

Centos7使用man查找命令时&#xff0c;报错No manual entry for xxxx 在Linux中使用man指令查找指令信息时&#xff0c;报No manual entry for xxxx。 比如使用man指令查找sleep3号手册时&#xff0c;出现以下错误&#xff1a; 这是由于没有安装man-pages这个rpm包导致的&#…

掌握基本排序算法:冒泡、选择、插入和快速排序

在计算机科学的世界里&#xff0c;排序是一项基本而重要的操作。无论是数据库管理、搜索引擎&#xff0c;还是日常编程&#xff0c;高效的排序算法都是提高性能的关键。本文将介绍四种基本的排序算法&#xff1a;冒泡排序、选择排序、插入排序和快速排序&#xff0c;并探讨它们…

从0开始学习NEON(1)

1、前言 在上个博客中对NEON有了基础的了解&#xff0c;本文将针对一个图像下采样的例子对NEON进行学习。 学习链接:CPU优化技术 - NEON 开发进阶 上文链接:https://blog.csdn.net/weixin_42108183/article/details/136412104 2、第一个例子 现在有一张图片&#xff0c;需…

获取 Windows 通知中心弹窗通知内容(含工具汉化)

目录 前言 技术原理概述 测试代码和程序下载连接 本文出处链接&#xff1a;https://blog.csdn.net/qq_59075481/article/details/136440280。 前言 从 Windows 8.1 开始&#xff0c;Windows 通知现在以 Toast 而非 Balloon 形式显示&#xff08; Bollon 通知其实现在是应用…

在ubuntu上安装hadoop完分布式

准备工作 Xshell安装包 Xftp7安装包 虚拟机安装包 Ubuntu镜像源文件 Hadoop包 Java包 一、安装虚拟机 创建ubuntu系统 完成之后会弹出一个新的窗口 跑完之后会重启一下 按住首先用ctrlaltf3进入命令界面&#xff0c;输入root&#xff0c;密码登录管理员账号 按Esc 然后输入 …

数据结构常用的字符串函数(中英双释)

头文件&#xff1a;string.h 1.strchr const char * strchr ( const char * str, int character ); Locate first occurrence of character in string str C string. character Character to be located. Return Value A pointer to the first occurrence of character in s…

适用于恢复iOS数据的 10 款免费 iPhone 恢复软件

现在&#xff0c;您可以获得的 iPhone 的存储容量比大多数人的笔记本电脑和台式电脑的存储容量还要大。虽然能够存储数千张高分辨率照片和视频文件、安装数百个应用程序并随身携带大量音乐库以供离线收听固然很棒&#xff0c;但在一个地方拥有如此多的数据可能会带来毁灭性的后…

2.2_5 调度算法

文章目录 2.2_5 调度算法一、适用于早期的批处理系统&#xff08;一&#xff09;先来先服务&#xff08;FCFS&#xff0c;First Come First Serve&#xff09;&#xff08;二&#xff09;短作业优先&#xff08;SJF&#xff0c;Shortest Job First&#xff09;&#xff08;三&a…

SpringMVC总结

SpringMVC SpringMVC是隶属于Spring框架的一部分&#xff0c;主要是用来进行Web开发&#xff0c;是对Servlet进行了封装。 对于SpringMVC我们主要学习如下内容: SpringMVC简介 请求与响应 REST风格 SSM整合(注解版) 拦截器 SpringMVC是处理Web层/表现层的框架&#xff…

易语言源代码5000例

仅供学习研究交流使用 加群下载

探索MyBatis-Plus的高阶用法

引言 MyBatis-Plus 是 MyBatis 的增强工具包&#xff0c;提供了许多方便快捷的功能来简化开发&#xff0c;提高效率。除了基本的 CRUD 操作外&#xff0c;MyBatis-Plus 还提供了一些高级功能&#xff0c;本文将探讨 MyBatis-Plus 的高阶用法&#xff0c;帮助开发者更好地利用该…

Linux服务器搭建超简易跳板机连接阿里云服务器

简介 想要规范内部连接阿里云云服务器的方式&#xff0c;但是最近懒病犯了&#xff0c;先搞一个简易式的跳板机过渡一下&#xff0c;顺便在出一个教程&#xff0c;其他以后再说&#xff01; 配置方法 创建密钥 登录阿里云&#xff0c;找到云服务器ECS控制台&#xff0c;点击…

【小白友好】LeetCode 打家劫舍 III

https://leetcode.cn/problems/house-robber-iii/description/ 前言 建议还是先看看动态规划的基础题再看这个。动态规划是不刷题&#xff0c;自己100%想不出来的。 基础题&#xff1a; 23 小白想法 现在我们想遍历的数据结构不是数组了&#xff0c;而是一颗树。在树上的d…

C++递推

统计每个月兔子的总数 #include<bits/stdc.h> using namespace std; int n,sum0; void f(int); int main() {int a[1000];cin>>n;a[1]1;a[2]2;for(int i3;i<1000;i){a[i]a[i-1]a[i-2];}cout<<a[n];return 0; } void f(int n){}猴子吃桃子 #include<b…

2024年华为OD机试真题-电脑病毒感染-Python-OD统一考试(C卷)

题目描述: 一个局域网内有很多台电脑,分别标注为0 - N-1的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t表示。 其中网络内一个电脑被病毒感染,其感染网络内所有的电脑需要最少需要多长时间。如果最后有电脑不会感染,则返回-1 给定一个数组times表示一个…

在Spring Boot中如何实现异常处理?

在Spring Boot中&#xff0c;异常处理可以通过几种方式实现&#xff0c;以提高应用程序的健壮性和用户体验。这些方法包括使用ControllerAdvice注解、ExceptionHandler注解、实现ErrorController接口等。下面是一些实现Spring Boot异常处理的常用方法&#xff1a; 1. 使用Cont…

Git实战(2)

git work flow ------------------------------------------------------- ---------------------------------------------------------------- 场景问题及处理 问题1&#xff1a;最近提交了 a,b,c,d记录&#xff0c;想把b记录删掉其他提交记录保留&#xff1a; git reset …

【C++ 编程指南】

C 编程指南 ■ C环境安装■ C 基本语法■ 预定义宏■ # 和 ## 运算符■ C 引用■ C 命名空间■ 定义命名空间■ using 指令■ 嵌套的命名空间 ■ String类■ 类■ 类的static静态成员 ■ C 继承■ 继承类型 public、protected 或 private■ 访问控制和继承■ 多继承■ 数据抽象…