hihocoder 1032 最长回文子串 (Manacher算法 详解+模板)

2024-03-20 13:38

本文主要是介绍hihocoder 1032 最长回文子串 (Manacher算法 详解+模板),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

时间限制:1000ms
单点时限:1000ms
内存限制:64MB

描述

   小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

   这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”

   小Ho奇怪的问道:“什么叫做最长回文子串呢?”

   小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”

   小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?

   小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”

提示一提示二提示三提示四
样例输入
3
abababa
aaaabaa
acacdas
样例输出
7
5
3 

题目链接:http://hihocoder.com/problemset/problem/1032


题目分析:Manacher算法可以在O(n)的时间复杂度内解决最长回文子串问题,下面介绍一下这个算法

首先对于一个任意长度的字符串,通过插入无关字符法均可以将其变成奇数长度,如aba => #a#b#a#,abba => #a#b#b#a#,为了解决边界问题可以直接在最前面再加上一个无关字符,令cur为当前能延伸到最右端的回文子串的中心位置,p[cur]表示当前能延伸到最右端的回文子串的回文半径,而p[cur] + cur就是当前能延伸到的最右端,当前位置i如果在其范围之外,即p[cur] + cur < i则p[i] = 1(自己另起一段回文子串),如果p[cur] + cur >= i,也就是当前位置在其范围内,则此时p[i] = min(p[cur * 2 - i],p[cur] + cur - i),这里分两种情况,1) p[cur * 2 - i] > p[cur] + cur - i,也就是说以i当前的对称点为中心的回文子串范围在当前cur为中心的回文子串的最左端的左边,则这时p[i] = p[cur] + cur - i;p[cur] + cur - i指的是当前cur为中心的回文串的最右端到当前点i的距离,2) p[cur * 2 - i] <= p[cur] + cur - i,情况类似上面,画图很容易看出来,算出p[i],则以当前的i为中心向两端扩展,若扩展出来的最右端超过原来的最右端则更新cur

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 1e6 + 5;
char s[MAX << 1];
int p[MAX << 1];int Manacher()
{int len = strlen(s);for(int i = len; i >= 0; i--){s[(i << 1) + 2] = s[i];s[(i << 1) + 1] = '#';}s[0] = '*';int cur = 0, ans = 0;for(int i = 2; i < 2 * len + 1; i++){if(p[cur] + cur >= i)p[i] = min(p[(cur << 1) - i], p[cur] + cur - i);elsep[i] = 1;while(s[i - p[i]] == s[i + p[i]])p[i] ++;if(p[cur] + cur < i + p[i])cur = i;ans = max(ans, p[i]);}return ans - 1;
}int main()
{int n;scanf("%d", &n);while(n --){scanf("%s", s);printf("%d\n", Manacher());}
}


这篇关于hihocoder 1032 最长回文子串 (Manacher算法 详解+模板)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829617

相关文章

Java中的stream流分组示例详解

《Java中的stream流分组示例详解》Java8StreamAPI以函数式风格处理集合数据,支持分组、统计等操作,可按单/多字段分组,使用String、Map.Entry或Java16record... 目录什么是stream流1、根据某个字段分组2、按多个字段分组(组合分组)1、方法一:使用 Stri

Spring创建Bean的八种主要方式详解

《Spring创建Bean的八种主要方式详解》Spring(尤其是SpringBoot)提供了多种方式来让容器创建和管理Bean,@Component、@Configuration+@Bean、@En... 目录引言一、Spring 创建 Bean 的 8 种主要方式1. @Component 及其衍生注解

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

springboot2.1.3 hystrix集成及hystrix-dashboard监控详解

《springboot2.1.3hystrix集成及hystrix-dashboard监控详解》Hystrix是Netflix开源的微服务容错工具,通过线程池隔离和熔断机制防止服务崩溃,支持降级、监... 目录Hystrix是Netflix开源技术www.chinasem.cn栈中的又一员猛将Hystrix熔

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

python之uv使用详解

《python之uv使用详解》文章介绍uv在Ubuntu上用于Python项目管理,涵盖安装、初始化、依赖管理、运行调试及Docker应用,强调CI中使用--locked确保依赖一致性... 目录安装与更新standalonepip 安装创建php以及初始化项目依赖管理uv run直接在命令行运行pytho

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.