当前位置: 首页 > news >正文

manacher算法详解

例题

  • 求一个字符串的最长回文子串的长度

O(N2)O(N^2)O(N2)的解法很容易想,就是从每个字符位置向左右同时拓展,然后检查当前是不是回文,更新长度,可以简单写一下代码

int solve(string &ss){int ans = 0;int n = ss.length();string s;s.resize(2 * n + 1);int l = 0;s[l++] = '$';s[l++] = '#';for(int i=0;i<n;i++){s[l++] = ss[i];s[l++] = '#';}for(int i=0;i<l;i++){int p = 0;while(i - p >= 0 && i + p < l && s[i + p] == s[i - p]){p += 1;}ans = max(ans, p - 1);}return ans;
}
  • 这里注意一个小技巧,一个字符串有两种情况,分别是长度为奇数和长度为偶数,如何将这两种情况归一化呢?考虑在字符串前面加一个$,在每两个字符之间放一个#,不一定非得是$和#,只要不会在字符串中出现即可,容易计算得到这样做得到的字符串长度一定是奇数
  • 考虑优化,容易想到如果计算已经得到了前面的回文半径(以某个字符为中心的回文串长度的一半),那么对称的两个点中尚未计算的那个点的回文半径的最小值也就是已经计算得到的那个点的回文半径
    在这里插入图片描述
  • 观察上面的字符串,第一个红色的b的回文半径容易求出是2,后面的c的回文半径容易求出是6,那么我们如何根据它求出后面的红色的b的回文半径呢?显然因为c的回文半径范围覆盖了第一个红色的b,所以第二个红色的b的回文半径的最小值是第一个红色的b的回文半径(这里同时因为c的回文半径也覆盖了第二个红色的b的回文半径区域,因为如果第二个红色的b之后没有足够的字符也是到不了第一个红色的b的回文半径的),这样我们就得到了第二个b的回文半径的最小值,然后暴力拓展,就为之后的字符串也做好了铺垫,可以证明总的时间复杂度是O(n)O(n)O(n)
  • 上面是我对manacher算法的个人理解,接下来从代码的角度来说一下,首先需要两个变量rc,因为有一个问题,怎么判断某个字符是不是在某个回文区间之内,我们可以从左边递推找到一个右端点最远的回文区域,这样记录一下中心端点c和右端点r,在从左到右计算的过程中更新最大的r,这样就找到了回文半径和回文中心
  • 然后使用一个数组P[i]记录以i为中心的回文半径,具体代码如下
int manacher(string &ss){int n = ss.length();string s;s.resize(2 * n + 1);int l = 0;s[l++] = '$';s[l++] = '#';for(int i=0;i<n;i++){s[l++] = ss[i];s[l++] = '#';}vector<int> P(l);int r, c;r = c = 0;int ans = 0;for(int i=0;i<l;i++){int &p = P[i];// 用r - i约束的原因上面已经说过p = (i + p < r ? min(r - i, P[2 * c - i]) : 1);// 2 * c - i是对称位置的字符while(s[i + p] == s[i - p]) p += 1;if(i + p > r){r = i + p;c = i;}ans = max(ans, p - 1);}return ans;
}

例题

https://www.luogu.com.cn/problem/P4287
在一个字符串里面找前后两个长度相等的子串都是回文串的字符串的最大长度

  • 考虑manacher,如果计算出了一个回文串,因为它的前面已经计算好了,比如现在回文半径右端点最远在rrr,那么从iiirrr这一段是回文串的一半我们是知道的,现在考虑它前面一段,怎么考虑呢?根据对称性,设j≥rj\geq rjr,对称到左边就是i−j−i2i-\frac{j-i}{2}i2ji同时还需要满足(j−i)%4=0(j-i)\%4=0(ji)%4=0,这里的iii是右侧字符串的回文中心,jjj是左侧字符串关于ccc对称的回文中心
  • 因为要求这样的回文串长度必须是偶数,所以根据我们的回文串构造方法,每次枚举的iii必须是奇数
#include <bits/stdc++.h>using namespace std;int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n;string ss;cin >> n >> ss;string s;s.resize(2 * n + 1);int l = 0;s[l++] = '$';s[l++] = '#';for(int i=0;i<n;i++){s[l++] = ss[i];s[l++] = '#';}vector<int> P(l);int r, c;r = c = 0;int ans = 0;for(int i=0;i<l;i++){int &p = P[i];p = (i + p < r ? min(P[2 * c - i], r - i) : 1);while(s[i + p] == s[i - p]) p += 1;if(i + p > r){if(i & 1){for(int j=max(r, i + 4);j<=i+p;j++){if((j - i) % 4 == 0 && P[i - (j - i) / 2] >= (j - i) / 2){ans = max(ans, j - i);}}}r = i + p;c = i;}}cout << ans << '\n';return 0;
}

相关文章:

manacher算法详解

例题 求一个字符串的最长回文子串的长度 O(N2)O(N^2)O(N2)的解法很容易想&#xff0c;就是从每个字符位置向左右同时拓展&#xff0c;然后检查当前是不是回文&#xff0c;更新长度&#xff0c;可以简单写一下代码 int solve(string &ss){int ans 0;int n ss.length();s…...

要做一个关于DDD的内部技术分享,记录下用到的资源,学习笔记(未完)

最后更新于2023年3月10日 14:28:08 问题建模》软件分层》具体结构&#xff0c;是层层递进的关系。有了问题建模&#xff0c;才能进行具体的软件分层的讨论&#xff0c;再有了分层&#xff0c;才能讨论在domain里面应该怎么实现具体结构。 1、问题建模&#xff1a;Domain、Mod…...

KDZD互感器二次负载测试仪

一、概述 电能计量综合误差过大是电能计量中普遍存在的一个关键问题。电压互感器二次回路压降引起的计量误差往往是影响电能计量综合误差的因素。所谓电压互感器二次压降引起的误差&#xff0c;就是指电压互感器二次端子和负载端子之间电压的幅值差相对于二次实际电压的百分数…...

在空投之后,Blur能否颠覆OpenSea的主导地位?

Mar. 2023, Daniel数据源&#xff1a; NFT Aggregators Overview & Aggregator Statistics Overview & Blur Airdrop一年前&#xff0c;通过聚合器进行的NFT交易量开始像滚雪球一样增长&#xff0c;有时甚至超过了直接通过市场平台的交易量。虽然聚合器的使用量从10月到…...

2023年新三板产品及服务研究报告

第一章 概述 全国中小企业股份转让系统&#xff08;英语&#xff1a;National Equities Exchange and Quotations&#xff0c;缩写NEEQ&#xff09;&#xff0c;简称股转系统&#xff0c;是第三家全国性证券交易场所&#xff0c;因挂牌企业均为高科技企业而不同于原转让系统内…...

张力控制之开环模式

张力控制的相关知识也可以参看专栏的其它文章,链接如下: 张力闭环控制之传感器篇(精密调节气阀应用)_RXXW_Dor的博客-CSDN博客跳舞轮对应张力调节范围,我们可以通过改变气缸的气压方式间接改变,张力跳舞轮在收放卷闭环控制上的详细应用,可以参看下面的文章链接,这里我…...

python的django框架从入门到熟练【保姆式教学】第二篇

在上一篇博客中&#xff0c;我们介绍了Django的基础知识&#xff0c;并创建了一个简单的Web应用程序。在本篇教程中&#xff0c;我们将深入探讨Django的模型层&#xff08;Model&#xff09;&#xff0c;它是Django应用程序的核心组件之一。 模型层 Django的模型层是一个对象…...

解决win10的过度保护导致文件下载不了程序不能打开运行

win7看来大概是要离我们远去了&#xff0c;虽然我们还能看见她的背影&#xff0c;但大势所趋&#xff0c;我们也只能慢慢的接受win10进入到我们的日常生活。但win10很多时候过度的保护却给我们带来了不便。这里列举两个最常见的问题&#xff0c;当然我这里也给出了解决方案。 文…...

扬帆优配|业务量大突破,这个行业发展明显向好

近期上市的新股&#xff0c;大都在招股阐明书里公布了本年第一季度成绩预告。 我国快递事务量本年已达200亿件 国家邮政局监测数据显现&#xff0c;到3月8日&#xff0c;本年我国快递事务量已到达200.9亿件&#xff0c;比2019年到达200亿件提前了72天&#xff0c;比2022年提前…...

DJ1-4 计算机网络和因特网

目录 一、协议层及其服务模型 ISO/OSI 七层参考模型 TCP/IP 参考模型 1. 网际协议栈&#xff08;protocol stack&#xff09; 2. 分层&#xff1a;逻辑通信 3. 协议分层与数据 二、攻击威胁下的网络 1. 植入恶意软件 2. 攻击服务器和网络基础设施 3. 嗅探分组 4. 伪…...

Nginx根据$host及请求的URI规则重定向rewrite

项目背景&#xff1a; 将域名请求从默认的80端口转发到443 ssl。本项目特殊之处是一个端口监听多个域名&#xff0c;某些域名还有跳转到特定的地址。 普通情况&#xff1a; server { listen 80; #默认的80端口&#xff0c;非…...

人工智能实验一:使用搜索算法实现罗马尼亚问题的求解

1.任务描述 本关任务&#xff1a; 了解有信息搜索策略的算法思想&#xff1b;能够运用计算机语言实现搜索算法&#xff1b;应用A*搜索算法解决罗马尼亚问题&#xff1b; 2.相关知识 A*搜索 算法介绍 A*算法常用于 二维地图路径规划&#xff0c;算法所采用的启发式搜索可以…...

Spring Security基础入门

基础概念 什么是认证 认证&#xff1a;用户认证就是判断一个用户的身份身份合法的过程&#xff0c;用户去访问系统资源的时候系统要求验证用户的身份信息&#xff0c;身份合法方可继续访问&#xff0c;不合法则拒绝访问。常见的用户身份认证方式有&#xff1a;用户密码登录&am…...

dnsresolver-limit

文件OperationLimiter.h功能DnsResolver是andnroid中提供DNS能力的小型DNS解析器&#xff0c;limit是其中的一个小模块&#xff0c;支持全局、基于key&#xff08;UID&#xff09;的DNS请求限制。DnsResolver是多线程模型&#xff0c;单个DNS请求最多启动3个线程(传统DNS)。在网…...

使用 YoctoProject集成Qt6

By Toradex胡珊逢在嵌入式领域中Qt 作为普遍选择的 UI 方案目前已经发布 Qt6 版本。本文将介绍如何为 Toradex 的计算机模块使用 Yocto Project 将 Qt6 集成到镜像里。首先根据这里的说明&#xff0c;准备好Yocto Project 的编译环境。这里我们选择 Toradex 最新的 Linux BSP V…...

「媒体邀约」如何选择适合的媒体公关,媒体服务供应商

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 每天胡老师也会接到大量关于媒体方面的询问&#xff0c;胡老师也都一一的很耐心的进行了解答&#xff0c;也都很详细的做了媒体规划和媒体传播方案&#xff0c;但有的朋友还是很犹豫&…...

html2canvas和jspdf导出pdf,每个页面模块占一页,在pdf中垂直居中显示

需求&#xff1a;html页面转换pdf&#xff0c;页面有多个模块&#xff0c;页面中有文本、echarts、表格等模块&#xff0c;一个模块占一页&#xff0c;因为模块高度不够&#xff0c;所以需要垂直居中 通过html2canvas和jspdf实现&#xff0c;html2canvas用于将页面元素生成canv…...

数学小课堂:集合论的公理化过程(用构建公理化体系的思路来构建自然数)

文章目录 引言I 数的理论1.1 构建自然数1.2 定义整数/有理数/实数/虚数/复数II 自然数和集合的关系1.3 集合1.2 构建自然数III 线性规划问题(线性代数+最优化)3.1 题目3.2 答案引言 数学是一个公理化的体系,是数学对其它知识体系有启发的地方。 数学的思维方式: 不轻易相信…...

3.10多线程

一.常见锁策略1.悲观锁 vs乐观锁体现在处理锁冲突的态度①悲观锁:预期锁冲突的概率高所以做的工作更多,付出的成本更多,更低效②乐观锁:预期锁冲突的概率低所以做的工作少,付出的成本更低,更搞笑2.读写锁 vs 普通的互斥锁①普通的互斥锁,只有两个操作 加锁和解锁只有两个线程针…...

缓存双写一致性之更新策略探讨

问题由来 数据redis和MySQL都要有一份&#xff0c;如何保证两边的一致性。 如果redis中有数据&#xff1a;需要和数据库中的值相同如果redis中没有数据&#xff1a;数据库中的值是最新值&#xff0c;且准备会写redis 缓存操作分类 自读缓存读写缓存&#xff1a; &#xff0…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

前端工具库lodash与lodash-es区别详解

lodash 和 lodash-es 是同一工具库的两个不同版本&#xff0c;核心功能完全一致&#xff0c;主要区别在于模块化格式和优化方式&#xff0c;适合不同的开发环境。以下是详细对比&#xff1a; 1. 模块化格式 lodash 使用 CommonJS 模块格式&#xff08;require/module.exports&a…...

Qt Quick Controls模块功能及架构

Qt Quick Controls是Qt Quick的一个附加模块&#xff0c;提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中&#xff0c;这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构&#xff0c;与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...

使用ch340继电器完成随机断电测试

前言 如图所示是市面上常见的OTA压测继电器&#xff0c;通过ch340串口模块完成对继电器的分路控制&#xff0c;这里我编写了一个脚本方便对4路继电器的控制&#xff0c;可以设置开启时间&#xff0c;关闭时间&#xff0c;复位等功能 软件界面 在设备管理器查看串口号后&…...