比KMP简单的Manacher

P3805 【模板】manacher - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

“没时间悼念KMP了,接下来上场的是Manacher!”


什么是Manacher?

历史背景:

1975 年,一个叫 Manacher 的人发明了这个算法,所以叫Manacher 算法(中文名:马拉车算法)

应用背景:

现在有个字符串A,你需要找到该字符串中最长的回文字串,输出其长度。

回文串是正着读反着读都是一样的,例如:101,aba,tnt。

Manacher算法思路:

Manacher第一步修改原字符串。

我们认定一个字符串是否为回文串,都会先找这个字符串的中心,然后向两边扩散进行字符对比。比如aba这个字符串,我们要判断它是否为回文串,就可以先找到中心位置b,然后再向两边扩散比较,b左边的字符是不是等于b右边的字符,如果都一致,那么该字符串就是回文串。

当然,聪明的你一定发现了一个问题,如果该字符串是abba这种偶数长度的字符串呢?这个时候我们就可以把偶数长度的字符串变为奇数长度的字符串,向原字符串插入一个原字符串不会出现的字符,比如,"$"。那么对于abba而言插入后的字符串就变成了$a$b$b$a$。然后我们就可以套用判断奇字符串是否是回文串的思想,来对这个进行判断了。

插入相同字符后的字符串如果是回文串,那么没有插入相同字符的字符串也是回文串,可自行验证。

所以Mannacher的第一步就是在原来的字符串的基础上,插入一个原字符串不会出现的字符。

Manacher第二步回文范围[L,R],回文中心W。

约定p数组放的是回文半径,则p[i]存放的是以i为回文中心的回文半径。

如图,在字符串(黑色框)中有一回文子串(蓝色框),范围为[L, R],其中M为该回文串的中心,现在我们欲求以i为回文中心的回文半径r。就要先分两种大情况。

第一种是i在[L, R]区间里,我们就可以先找i相当于M的对称点K,因为i是在K之后的所以K的回文半径是已知的,那么当K的回文区域不包含L,即K-p[K]+1>L时,p[i] = p[k] =[2*M-i]。当K的回文区域包含L时,即K-p[K]+1<=L时,p[i] = R-i+1。

第二种是i在[L, R]区间外面的,我们就只能暴力向两边扩散比较,求得它的回文半径。

经过如图的数学推导,我们就可以给第一种情况化简为p[i]=min(p[2*M-i], R-i+1),然后再向两边扩散比较字符。

通过以上这种方法,写一个for循环加一层while就能够快捷地得到以每个字符作为回文中心的回文半径了。

得到回文半径有什么用呢?题目不是让我们求字符串里面最长的回文子串有多长嘛?那么最大的回文半径-1,不就是最长的回文子串的长度嘛?也就解开了。

因为原字符串在插入了原字符串没有的字符后,原字符串的长度变成了原来的2倍,所以回文半径-1就是最长的回文子串。可自己写几个试试。

【算法详解】Manacher算法_哔哩哔哩_bilibili 


如何实现Manacher代码?

插入原字符串没有的字符

for (ll i = 0; i < 2 * a.length(); i++)
	{
		if (i & 1)
//如果是奇数
			b[i] = a[i / 2];

		else
			b[i] = '$';
	}
	b[2 * a.length()] = '$';
//a为原字符串
//b为插入后的字符串

求以每个字符作为回文中心的回文半径

ll M = 0, R = 0;
//初始化M和R
	for (ll i = 0; i <= 2 * a.length(); i++)
	{
// for循环遍历字符串里面每个字符
		if (i > R)
			p[i] = 1;
//如果i是在[L, R]区间外面的 
//那么它的回文半径默认从1开始
		else
			p[i] = min(p[2 * M - i], R - i + 1);
//否则回文半径就是min(p[2 * M - i], R - i + 1)
		while (i + p[i]<= 2 * a.length() && i - p[i] >= 0 && b[i - p[i]] == b[i + p[i]])
//while循环就是向两边扩散比较的过程
			p[i]++;
//只有当左右两边的字符一致
//回文半径才+1
		if (i + p[i] - 1 > R)
		{
			M = i;
			R = i + p[i] - 1;
		}
//如果以新的字符为回文中心
//回文半径更大的话
//那么就以新的字符为回文中心
//更新R
	}

全部代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll N = 2e7;
string a;
vector<ll> p(2 * N);
char b[2 * N];

int main()
{
	cin >> a;
	for (ll i = 0; i < 2 * a.length(); i++)
	{
		if (i & 1)
			b[i] = a[i / 2];

		else
			b[i] = '$';
	}
	b[2 * a.length()] = '$';
	// cout << "变形后的:" << b << endl;
	ll M = 0, R = 0;
	for (ll i = 0; i <= 2 * a.length(); i++)
	{
		if (i > R)
			p[i] = 1;
		else
			p[i] = min(p[2 * M - i], R - i + 1);
		while (i + p[i]<= 2 * a.length() && i - p[i] >= 0 && b[i - p[i]] == b[i + p[i]])
			p[i]++;
		if (i + p[i] - 1 > R)
		{
			M = i;
			R = i + p[i] - 1;
		}
	}
	// cout << M << " " << R << endl;

	cout << *max_element(p.begin(), p.end()) - 1;

	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaWeb】Day28.SpringBootWeb请求响应——请求(一)

前言&#xff1a; 我们在开发web程序时呢&#xff0c;定义了一个控制器类Controller&#xff0c;请求会被部署在Tomcat中的Controller接收&#xff0c;然后Controller再给浏览器一个响应。 而在请求响应的过程中是遵循HTTP协议的。 但是&#xff0c;在Tomcat这类Web服务器中&a…

vivado JTAG 回退支持

JTAG 回退支持 基于 XVC 的调试解决方案可配合 AXI 主接口 &#xff08; 如 PCIe XDMA IP &#xff09; 一起使用。如果 AXI 主接口被挂起 &#xff0c; 或者无法正常 运作&#xff0c; 则无法在此类情况下进行调试。为了提供基于 JTAG 的回退调试途径 &#xff08; 与 X…

【Java多线程】8——CompletableFuture

8 CompletableFuture ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记仓库&#x1f449;https://github.com/A-BigTree/tree-learning-notes 个人主页&#x1f449;https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个s…

Native Instruments Kontakt 7 for Mac v7.9.0 专业音频采样

Native Instruments Kontakt 7是一款强大的软件采样器&#xff0c;它允许用户从各种来源采样音频并进行编辑和处理。它包含大量预设采样库&#xff0c;包括乐器、合成器、鼓组和声音效果等。此外&#xff0c;Kontakt 7还允许用户创建自己的采样库&#xff0c;以便根据自己的需要…

排列函数与组合函数

总实现&#xff1a; #include <iostream> using namespace std; long long CC(int a, int b)//求组合函数&#xff0c;a为C的下标&#xff0c;b为C上标&#xff0c;即:Ca!/(b!*(a-b)!) {int res 1; //记录结果for (int i a, j 1; j < b; i--, j){res * i / j;}r…

2025第四届CHWE出海网全球跨境电商展览会

2025第四届CHWE出海网全球跨境电商展览会 时间&#xff1a;2025年3月20-22日 地点&#xff1a;深圳会展中心&#xff08;福田&#xff09; 预订以上展会详询陆先生 I38&#xff08;前三位&#xff09; I82I&#xff08;中间四位&#xff09; 9I72&#xff08;后面四位&am…

数据结构(六)——图的遍历

6.3 图的遍历 6.3.1 图的广度优先遍历 ⼴度优先遍历&#xff08;Breadth-First-Search, BFS&#xff09;要点&#xff1a; 1. 找到与⼀个顶点相邻的所有顶点 2. 标记哪些顶点被访问过 3. 需要⼀个辅助队 FirstNeighbor(G,x)&#xff1a;求图G中顶点x的第⼀个邻接点&#xff…

小练习——if,switch语句,根据年份计算生肖

需求&#xff1a;根据用户输入的年份计算他是什么生肖 举例&#xff1a;输入2024年&#xff0c;控制台会显示你属龙 所用技术&#xff1a;控制台输入 Scanner if 语句 / switch语句 控制台输入 Java控制台输入的三种实现方法&#xff1a;使用标准输入对象System.in&#xff…

C语言预处理详解

前言 上篇博客我们总结了编译与链接&#xff0c;有说过编译里第一步是预处理&#xff0c;那本篇博客将对预处理进行进一步的详细的总结 个人主页&#xff1a;小张同学zkf 若有问题 评论区见 感兴趣就关注一下吧 目录 1. 预定义符号 2. #define 定义常量 3. #define定义宏 4…

零失误微信支付商家转账到零钱功能开通教程

商家转账到零钱是什么&#xff1f; 使用商家转账到零钱这个功能&#xff0c;可以让商户同时向多个用户的零钱转账。商户可以使用这个功能用于费用报销、员工福利发放、合作伙伴货款或分销返佣等场景&#xff0c;提高效率。 商家转账到零钱的使用场景有哪些&#xff1f; 商家…

如何使用Axure RP制作网页原型并结合IIS服务实现公网访问本地HTML网页

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

STM32CubeIDE基础学习-RS232通信

STM32CubeIDE基础学习-RS232通信 文章目录 STM32CubeIDE基础学习-RS232通信前言第1章 工程配置第2章 代码编写第3章 实验现象总结 前言 RS232也是串口的一种&#xff0c;RS-232是由电子工业协会(Electronic Industries Association, EIA)所制定的异步传输标准接口。在1962年发布…

sql之每日五题day01--多表联查/聚合函数

sql错题记录 含有聚合函数的不能用where升序排列order byleft join多表联查inner join不返回null三表联查 含有聚合函数的不能用where SQL19 分组过滤练习题 题目&#xff1a;现在运营想查看每个学校用户的平均发贴和回帖情况&#xff0c;寻找低活跃度学校进行重点运营&#x…

PHP远程命令执行与代码执行原理利用与常见绕过总结

PHP远程命令执行与代码执行原理利用与常见绕过总结 远程命令执行 相较于SQL注入漏洞&#xff0c;远程命令执行更加少见。由于是直接执行系统命令&#xff0c;所以相较于前者此漏洞会更加危险&#xff1a; 攻击者通过远程命令执行漏洞可以直接掌控服务器攻击者可以通过存在此…

C语言:动态内存管理(二)

目录 前言 1.3 realloc​编辑 3、常见动态内存管理错误 3.1 对空指针的解引用操作 3.2 对动态开辟的空间进行越界访问 3.3 对非动态开辟内存使用free释放 3.4 使用free释放一块动态内存开辟的一部分 3.5 对同一块空间的多次释放 3.6 动态内存开辟之后忘记释放 总结 前…

python用户管理系统(加密)

在用户管理系统中使用哈希算法对用户密码进行加密处理 import hashlibusers []# 用户类&#xff0c;包含基本信息 class User:def __init__(self, name, password, emailNone):self.name nameself.password self._encrypt_password(password) # 加密密码self.email email…

ViveNAS性能调试笔记(一)

ViveNAS是一个开源的NAS文件服务软件&#xff0c;有一套独立自创的架构&#xff0c;ViveNAS希望能做到下面的目标&#xff1a; - 能支持混合使用高性能的介质(NVMe SSD)和低性能介质&#xff08;HDD&#xff0c;甚至磁带&#xff09;。做到性能、成本动态均衡。因此ViveNAS使用…

力扣刷题Days28-第二题-11.盛水最多的容器(js)

目录 1&#xff0c;题目 2&#xff0c;代码 3&#xff0c;学习与总结 3.1思路回顾 1&#xff0c;如何遍历 2&#xff0c;算法流程 3.2剖析问题 1&#xff0c;题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, h…

WordPress AutomaticPlugin SSRF漏洞复现(CVE-2024-27954)

0x01 产品简介 WordPress是一款免费开源的内容管理系统(CMS),最初是一个博客平台,但后来发展成为一个功能强大的网站建设工具,适用于各种类型的网站,包括个人博客、企业网站、电子商务网站等,并逐步演化成一款内容管理系统软件。 0x02 漏洞概述 WordPress AutomaticPlu…

jsp中设置动态时间

第一步 在head中写入meta <head><meta charset"UTF-8" http-equiv"Refresh" content"1"> </head> 第二步在head中写入函数 <head><meta charset"UTF-8" http-equiv"Refresh" content"…