5.最长回文子串——Manacher(马拉车)算法

news2025/1/10 23:31:10

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

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

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


示例 2:

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

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

自己写的:超出时间限制了

class Solution {
public:
    string longestPalindrome(string s) {
        int len = s.length();
        string rets;
        bool flag = false;
        for(int i = 0;i<len;i++)
        {
            for (int j=0;j<len-i;j++)
            {
                int left = j;
                int right = i+j;
                while(left<=right)
                {
                    flag = true;
                    if(s[left]!=s[right])
                    {
                        flag = false;
                        break;
                    }
                    left++;
                    right--;
                }
                if(flag)
                    rets = s.substr(j, i+1);
            }
        }
        return rets;
    }
};

第二解法:

class Solution {
public:
    string longestPalindrome(string s) {

        string rets="";
        for(int i =0;i<s.length();i++)
        {
            //奇数
            int l =i-1,r=i+1;
            while(l>=0&&r<s.length()&&s[l]==s[r]) l--,r++;
            if(rets.length()<r-l-1) rets=s.substr(l+1,r-l-1);//因为l减1了,所有此处加1

            //偶数
            l=i,r=i+1;
            while(l>=0&&r<s.length()&&s[l]==s[r]) l--,r++;
            if(rets.length()<r-l-1) rets=s.substr(l+1,r-l-1);//因为l减1了,所有此处加1
        }
        return rets;
    }
};

示例模板:

Manacher算法:可以在O(n)的时间内求出一个字符串的最长回文串。

第一步:改造字符串

在字符串之间和串两端插入#,改造后,都变成奇回文串,方便统一处理。

奇回文串aba     #a#b#a#

偶回文串abba   #a#b#b#a#

s[0] = '$' 是哨兵(边界)

//改造串
scanf("%s",a+1);
int n = strlen(a+1),k=0;
s[0]='$',s[++k]='#';
for(int i=1;i<=n;i++)
    s[++k]=a[i],s[++k]='#';
n=k;

第二步:回文半径d[i]

以i为中心的最长回文串的长度的一半,叫回文半径。

i     1  2  3  4  5  6  7  8  9

s    #  a  #  a  #  b  #  a  #

d[i] 1  2  3  2  1  4  1  2  1

以b为例:b的最长回文#a#b#a#,长度为7,向上取整,回文半径为4。

第三步:加速盒子[l,r]

算法过程中我们维护右端点最靠右的最长回文串,利用盒子,借助之前的状态来加速计算新的状态。盒内d[i]可以利用对称点的d值转移,盒外暴力。

i     1  2  3  4  5  6  7  8  9

s    #  a  #  a  #  b  #  a  #

d[i] 1  2  3  2  1  4  1  2  1

算法流程:

计算完前i-1个d的函数,维护盒子[l,r]

1.如果i<=r(在盒内),i的对称点为r-i+l;

(1)若d[r-i+l]<r-i+1(对称点回文半径还在盒内),则d[i]=2*mid-i。

(2)若d[r-i+l] > r-i+1(对称点回文半径还在盒外),则令d[i]=r-i,从r往后暴力枚举。

2.如果i>r(在盒外),则从i开始暴力枚举。

3.求出d[i]后,如果i+d[i]-1>r,则更新盒子l=i-d[i]+1,r=i+d[i]-1。

class Solution {
public:
    static const int N = 1010, M = 2 * N;
    char str[M];
    int ls[M];
    string manacher(string s) {
        int l = 0, r = 0, mid = 0;
        int cur = 0;
        int n = s.size();
        str[l++] = '$';
        str[l++] = '#';
        for (int i = 0; i < s.size(); ++i) {
            str[l++] = s[i];
            str[l++] = '#';
        }
        str[l] = 0;

        for (int i = 0; i < l; ++i) {
            ls[i] = r > i ? min(ls[2 * mid - i], r - i) : 1; //在盒内的处理
            while (i - ls[i] > 0 && i + ls[i] < l) //在盒外的处理
                if (str[i - ls[i]] == str[i + ls[i]])ls[i]++;
                else break;
            if (i + ls[i] > r) {
                r = i + ls[i];
                mid = i;
            }
            if (ls[i] > ls[cur])cur = i;
        }
        // cout<<str<<endl;
        // cout<<cur<<endl;
        int left = cur - ls[cur] + 1, right = cur + ls[cur] - 1;
        string res = "";
        for (int i = left; i <= right; ++i) {
            if (str[i] != '#' && str[i] != '$')res += str[i];
        }
        return res;
    }
    string longestPalindrome(string s) {
        return manacher(s);
    }
};

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

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

相关文章

【计算机组成原理】第三章 多层次的存储器

系列文章目录 第一章 计算系统概论 第二章 运算方法和运算器 第三章 多层次的存储器 第四章 指令系统 第五章 中央处理器 第六章 总线系统 第七章 外围设备 第八章 输入输出系统 文章目录 系列文章目录前言第三章 多层次的存储器3.1 存储器概述3.1.1 存储器的分类3.1.2 存储器…

软件性能测试有哪些测试指标?性能测试报告怎么编写?​

软件性能测试是软件测试过程中非常重要的一部分&#xff0c;它可以保证软件在正式上线之前的稳定性和可靠性。那么&#xff0c;在进行软件性能测试时&#xff0c;我们需要关注哪些测试指标呢?性能测试报告又应该如何编写呢? 一、软件性能测试的测试指标 1.响应时间 响应时…

为github项目提交补充(pr)教程

记录第一次提交PR 前言为github提交补充什么是PR&#xff1a;Fork&#xff1a;git clone自己仓库&#xff1a;git remote add upstream和他人仓库建立关系&#xff1a;git checkout branch名切换分支&#xff1a;开始DIY项目文件&#xff1a;推送修改到自己仓库&#xff1a;空H…

c高级day4

一、编写一个名为myfirstshell.sh的脚本&#xff0c;它包括以下内容。 1、包含一段注释&#xff0c;列出您的姓名、脚本的名称和编写这个脚本的目的 2、和当前用户说“hello 用户名” 3、显示您的机器名 hostname 4、显示上一级目录中的所有文件的列表 5、显示变量PATH和H…

5.11总结:train/eval/BN、CNN与特征图、极大似然与EM、方差n与n-1(有偏估计/无偏估计)

目录 1.关于模型的train/eval与batchnorm1-1.理论1-2.实际运用&#xff08;包含loss反向传播&#xff09; 2.CNN详解&#xff0c;特征图是什么CNN处理过程特征图&#xff08;也叫通道&#xff09;(num_features)总结&#xff08;包含CNN图片的规律分析&#xff09;&#xff1a;…

SpringBoot基础篇3(SpringBoot+Mybatis-plus案例)

环境搭建&#xff1a;配置起步依赖pom.xml和配置文件application.yml 1.创建模块时&#xff0c;勾选的依赖有springMVC和MySQL驱动 2.手动添加的依赖有&#xff1a;MyBatis-plus、Druid、lombok <dependencies><dependency><groupId>org.springframework.…

Java笔记_20(多线程JUC)

一、多线程 1.1、多线程概述 进程 进程是程序的基本执行实体 线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。简单理解:应用软件中互相独立&#xff0c;可以同时运行的功能 什么是多线程? 有了多线程&#xf…

SpringBoot整合JPA

JPA、Hibernate、Spring Data JPA的关系 JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。Sun引入新的JPA ORM规范出于两个原因&…

从零入门激光SLAM(九)——三维点云基础

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。随着知识的越来越多&#xff0c;越来越细&#xff0c;我准备整理一个自己的激光SLAM学习笔记专栏&#xff0c;从0带大家快速上手激…

新品发布全线添员,九号全力奔向“红海”深处?

5月10日&#xff0c;九号公司2023新品发布会声势达到顶峰。此次发布会的看点为九号电动2023产品线的更新&#xff0c;电动家族再添多员大将。 随着人们出行选择的多样化&#xff0c;国内短途出行工具发展迎来井喷期。在传统的电动两轮车市场上&#xff0c;雅迪、爱玛等品牌仍然…

基于java(springboot)和go-cqhttp实现QQ机器人

目录 yh-qqrobot机器人简介go-cqhttp搭建1.下载应用2.生成bat文件3. 初始化项目4. 配置5. 运行项目 yh-qqrobot搭建搭建后端1. 导入sql文件2. 配置文件3. 导入到idea 搭建前端 yh-qqrobot机器人简介 yh-qqrobot是一个基于若依框和go-cqhttp集成的系统&#xff0c;一开始我只是揣…

生成一个简版导游地图

目录 1 简版导游地图功能简介 2 注册并登录 3 设置景区&#xff08;商圈&#xff09;地图 3.1 新增景区 3.2 增加一个景点介绍 3.3 地图中增加一个景点 3.4 增加几个其他类型的点&#xff0c;如“美食”、“购物”、“停车” 4 申请审核 5 欣赏一下 1 简版导游地图功能…

【python 异常处理】零基础也能轻松掌握的学习路线与参考资料

Python 异常处理是编写高质量、功能稳定程序的关键之一&#xff0c;它可以帮助开发者优化程序的稳定性和可读性&#xff0c;更好地管理代码的错误和异常情况。 本文将介绍 Python 异常处理的学习路线、参考资料和优秀实践&#xff0c;以帮助 Python 开发者提高应对程序中错误和…

华为OD机试真题 Java 实现【微服务的集成测试】【2023Q1 100分】

一、题目描述 现在有n个容器服务&#xff0c;服务的启动可能有一定的依赖性&#xff08;有些服务启动没有依赖&#xff09;&#xff0c;其次服务自身启动加载会消耗一些时间。 给你一个 nxn 的二维矩阵 useTime&#xff0c;其中 useTime[i][i]10 表示服务 i 自身启动加载需要消…

十大排序算法

1.冒泡排序 步骤:从头元素开始比较每一对相邻元素&#xff0c;如果第1个比第2个大&#xff0c;就交换它们的位置&#xff0c;执行完一轮&#xff0c;最末尾的那个元素就是最大的元素 1.1冒泡算法 void BubbleSort(int arr[], size_t length) {for (int end length-1; end &…

.netcore3.1+jenkins+Docker

一.git安装 1.下载 https://github.com/git/git/releases/tag/v2.40.1 2.将本地的安装包上传到 linux 服务器上&#xff0c;我这里放在 /opt/git/ 目录下 3.解压压缩包&#xff0c;得到目录 git-2.40.1&#xff0c;位置在 /opt/git/git-2.40.1 tar -zxvf git-2.40.1.tar.gz 4.…

AIGC产业研究报告2023——视频生成篇

易观&#xff1a;今年以来&#xff0c;随着人工智能技术不断实现突破迭代&#xff0c;生成式AI的话题多次成为热门&#xff0c;而人工智能内容生成&#xff08;AIGC&#xff09;的产业发展、市场反应与相应监管要求也受到了广泛关注。为了更好地探寻其在各行业落地应用的可行性…

【1++的C++初阶】之类与对象

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C初阶】 文章目录 一&#xff0c;面向对象与面向过程二&#xff0c;类2.1 类的定义2.2 类的访问限定符2.3 封装2.3.1 什么是封装2.3.2 封装的作用 2.4 类与对象 三&#xff0c;this指针3.1 什…

Docker 应用部署-MySQL

一、安装MySQL 1搜索mysql镜像 docker search mysql 2拉取mysql镜像 docker pull mysql:8.0.20 3创建容器 通过下面的命令&#xff0c;创建容器并设置端口映射、目录映射 #在用户名目录下创建mysql目录用于存储mysql数据信息 mkdir /home/mysql cd /home/mysql #创建docker容…

【数据结构】[LeetCode138. 复制带随机指针的链表]

一.问题描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值…