求回文子串O(n) manacher 算法

求最长回文子串的Manacher算法 最长回文子串以前一直是用后缀数组求的,今天看到一篇好文章写求O(n)求最长回文串的做法,所以呢就做个笔记 http://zhuhongcheng.wordpress.com/2009/08/02/a-simple-linear-time-algorithm-for-finding-longest-palindrome-sub-string/   英文的 http://acm.uestc.e 阅读详情
回文串定义:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”
等等就是回文串。
回文子串,顾名思义,即字符串中满足回文性质的子串。
经常有一些题目围绕回文子串进行讨论,比如HDOJ_3068_最长回文,求最长回文子
串的长度。朴素算法是依次以每一个字符为中心向两侧进行扩展,显然这个复杂度是O(N^2)
的,关于字符串的题目常用的算法有KMP、后缀数组、AC 自动机,这道题目利用扩展KMP
可以解答,其时间复杂度也很快O(N*logN)。但是,今天笔者介绍一个专门针对回文子串

的算法,其时间复杂度为O(n),这就是manacher 算法。

回文串定义:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”
等等就是回文串。
回文子串,顾名思义,即字符串中满足回文性质的子串。
经常有一些题目围绕回文子串进行讨论,比如HDOJ_3068_最长回文,求最长回文子
串的长度。朴素算法是依次以每一个字符为中心向两侧进行扩展,显然这个复杂度是O(N^2)
的,关于字符串的题目常用的算法有KMP、后缀数组、AC 自动机,这道题目利用扩展KMP
可以解答,其时间复杂度也很快O(N*logN)。但是,今天笔者介绍一个专门针对回文子串
的算法,其时间复杂度为O(n),这就是manacher 算法。
大家都知道,求回文串时需要判断其奇偶性,也就是求aba 和abba 的算法略有差距。
然而,这个算法做了一个简单的处理,很巧妙地把奇数长度回文串与偶数长度回文串统一考
虑,也就是在每个相邻的字符之间插入一个分隔符,串的首尾也要加,当然这个分隔符不能
再原串中出现,一般可以用‘#’或者‘$’等字符。例如:
原串:abaab
新串:#a#b#a#a#b#

这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。
算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。P[id]记录的是以字符str[id]为中心的最长回文串,当以str[id]为第一个字符,这个最长回文串向右延伸了P[id]个字符。
原串: w aa bwsw f d
新串: # w# a # a # b# w # s # w # f # d #
辅助数组P: 1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1


这里有一个很好的性质,P[id]-1就是该回文子串在原串中的长度(包括‘#’)。如果这里不是特别清楚,可以自己拿出纸来画一画,自己体会体会。当然这里可能每个人写法不尽相同,不过我想大致思路应该是一样的吧。
好,我们继续。现在的关键问题就在于怎么在O(n)时间复杂度内求出P数组了。只要把这个P数组求出来,最长回文子串就可以直接扫一遍得出来了。
由于这个算法是线性从前往后扫的。那么当我们准备求P[i]的时候,i以前的P[j]我们是已经得到了的。我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。(注:为了防止字符比较的时候越界,我在这个加了‘#’的字符串之前还加了另一个特殊字符‘$’,故我的新串下标是从1开始的)

void Manacher(int *rad, char *str, int n) { /* str 是这样一个字符串(下标从1开始):
	举例:若原字符串为"abcd",则str为"$#a#b#c#d#",最后还有一个终止符。
	n为str的长度,若原字符串长度为nn,则n=2*nn+2。
	rad[i]表示回文的半径,即最大的j满足str[i-j+1...i] = str[i+1...i+j],
	而rad[i]-1即为以str[i]为中心的回文子串在原串中的长度*/
	int i, id = 0, mx = 0;
	for(i = 1; i < n; i++) {
		if(mx > i) {
			rad[i] = min(rad[2*id - i], mx - i);
		}
		else rad[i] = 1;

		while(str[i+rad[i]] == str[i-rad[i]]) rad[i]++;

		if(rad[i] + i > mx) {
			mx = i + rad[i]; 
			id = i;
		}
	}
}

代码是不是很短啊,而且相当好写。很方便吧,还记得我上面说的这个算法避免了很多不必要的重复匹配吧。这是什么意思呢,其实这就是一句代码。

if( mx > i)
p[i]=MIN( p[2*id-i], mx-i);

就是当前面比较的最远长度mx>i的时候,P[i]有一个最小值。这个算法的核心思想就在这里,为什么P数组满足这样一个性质呢?
(下面的部分为图片形式)




看完这个算法,你有可能会觉得这种算法在哪会用到呢?其实回文串后缀数组也可以做。只是复杂度是O(n log n)的,而且一般情况下也不会刻意去卡一个log n的算法。可正好hdu就有这么一题,你用后缀数组写怎么都得T(当然应该是我写得太烂了)。不信的话大家也可以去试试这题。



【SPSS实战】手动实现Quade非参数协方差分析:从数据准备到结果解读 本文详细介绍了在SPSS中手动实现Quade非参数协方差分析的实战方法。当数据不满足正态分布等参数检验假设时,通过将协变量和因变量转换为秩,并利用秩回归残差进行Kruskal-Wallis组间比较,提供了一种清晰、可操作的近似解决方案。该方法有效解决了非正态数据的协变量调整问题,适用于实验研究和调查数据分析。 阅读详情

相关推荐

【COMSOL】将一个面上数据导出CSV或txt格式的方法

在COMSOL中参数化扫描后,把一个面上或体里的数据按照CSV或TXT格式导出的方法。

dave496206的博客 2991

Manacher算法--O(n)内求回文子串

昨天做了leetcode里的     Longest Palindromic Substring ,一开始用动态规划O(N^2),不管怎么改都超时了。。。于是在大神的帮助下,找到了传说中的Manacher算法,居然能在O(n)内求出来,瞬间给跪了。 本屌认为,这个算法主要是充分的利用了以前的匹配的结果,来起到了降低时间复杂度的作用,这点跟KMP算是有点类似。在预处理时有个小技巧就是将第0,1为设

黑暗之神 1510

Android 10 根文件系统和编译系统(十):Android.mk编译动态库

配套系列教学视频链接: Android 10.0 AOSP源码编译: 2-AOSP源码开发环境搭建 Android 10.0 根文件系统和编译系统: 3-Android根文件系统和编译系统 说明 系统:AOSP Android10.0 设备:Android模拟器 前言 本文章重点讲解Android.mk如何控制编译源码编译成动态库 ...

ldswfun的专栏 932

求回文子串 O(n) manacher算法

PDF:http://www.kuaipan.cn/file/id_32020291156705326.html回文串定义:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。回文子串,顾名思义,即字符串中满足回文性质的子串。经常有一些题目围绕回文子串进行讨论,比如 HDOJ_3068_最长回文,求最长回文子串的长度。朴素算法是依次以每一个字符为中心向两侧进

zz_zigzag的专栏 2222

LAMMPS in文件详解:从零开始手把手教你配置金属分子动力学模拟

本文详细解析了LAMMPS in文件的配置方法,手把手教你完成金属分子动力学模拟的全流程。从软件环境准备、势函数选择,到使用Materials Studio构建模型、编写in文件进行能量最小化与系统弛豫,再到实施单轴拉伸生产模拟并提取应力应变数据,最后通过Python和OVITO进行结果分析与可视化,提供了完整的实战指南和常见问题排查技巧。

weixin_28475533的博客 528

西门子PLC新手必看:200SMART与1200/1500的MODBUS RTU通讯实战(附完整配置流程)

本文详细解析了西门子PLC中S7-200 SMART与S7-1200/1500之间实现MODBUS RTU通讯的完整实战流程。内容涵盖硬件接线、软件配置及程序编写,重点讲解了200SMART作为从站、1200/1500作为主站的典型架构,并提供了关键功能块的使用方法和常见问题排查技巧,帮助新手快速打通不同系列PLC间的数据交换。

weixin_29214559的博客 398

O(n)时间求 最长回文子串 Manacher算法

回文字符串分为奇回文和偶回文,在字符串中间插入任意字符使得串变成奇回文串 暴力思想:肯定是找一个点往两边任意扩展,遍历一次, Manacher时间为O(n) 开一个数组p[]记录 以点i为中点 的最长回文串的半径, 假设前i-1个点的p[]都已经求出来来,现在考虑p[i]如何推导 重点: R是p[1]~p[i-1]中推出来的右端最远最长回文子串的右端点,且用pos记录下来,每一步更新pos...

_llc的博客 169

【开关电源】开关电源实战经验分享

开关电源原理设计、Layout设计经验分享

weixin_42098658的博客 4170

manacher算法 O(n)求最长回文子串

朴素的做法是求出以每个字符为中心的回文串长度,复杂度为,还需要考虑奇数长度和偶数长度。 而manacher算法可以在O(n)时间内求解,奇数长度和偶数长度可以统一处理。根据回文串的对称性,避免了大量不必要的比较。 处理技巧: ①相邻的字符之间插入一个分隔符,串的首尾也要加,以“#”为例,则长度为n的字符串经过处理之后变成2n+1奇数长度的字符串。为防止向两边扩展时越界,可以在首尾处加两个不匹

ww32cc的博客 559

【华为OD机试】2024年真题C卷(python)-API集群负载统计

【华为OD机试】-API集群负载统计-【华为OD机试】-API集群负载统计:某个产品的 restful API 集合部署在服务器集群的多个节点上,近期对客户端访问日志进行了采集,需要统计各个API的访问频次,根据热点信息在服务器节点之间做负载均衡,现在需要实现热点信息统计查询功能。 restful API 是由多个层级构成,层级之间使用/连接,如 A/B/C/D 这个地址,A属于第一级,B属于第二级,C属于第三级,D属于第四级。 现在负载均衡模块需要知道给定层级上某个名字出现的频次,未出现过用0

u014481728的博客 1495

【网络安全】AntSword蚁剑新手快速入门(附实战案例)

蚁剑(AntSword)是一款开源的跨平台WebShell管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。蚁剑的特点主要有如下几点:1.支持多平台。包括macOS、Linux 32位、Linux 64位、Linux armv7l、Linux arm64、Windows 32位、Windows 64位。2.完善的文档。中国蚁剑文档地址。3.多项功能。文件管理功能、虚拟终端功能、数据库管理功能。4.内置代理功能。

等风来 1万+

manacher算法 (O(n)求最长回文子串)

我们可以用O(n^2)暴力求解最长回文子串。 之所以是这个复杂度,是因为我们对每个字符比较其两边元素是否相等时,我们都是从它最旁边的一个开始迭代的。 但如果我们能以该字符为中心,其附近的某一段子串已为回文,在此基础上比较更远的元素,那么就有可能降低这个复杂度了。

Stephen Wong的专栏 2041

从0入门LocoTrack:6倍加速的SLAM追踪新范式实战指南

传统点追踪方法(如CorrTracker、TAPIR)在处理大规模场景或实时任务时,要么精度不足,要么速度太慢。而LocoTrack通过“局部4D相关性”和“Transformer全局关联”的创新设计,实现了精度与速度的双重突破速度:比现有SOTA方法快6倍,吞吐量高达数万点/秒;精度:在Kinetics、DAVIS等数据集上,定位误差显著低于传统方法;鲁棒性:能应对低纹理、动态场景等复杂环境,这是传统方法的“噩梦场景”。

m0_71589036的博客 95

Manacher 算法详解:O(n) 复杂度求最长回文子串

先预处理下:在每个字符的两边都插入一个特殊的符号,比如abba变成#a#b#b#a#,aba变成#a#b#a#(因为Manacher算法只能处理奇数长度的字符串)。同时,为了避免数组越界,在字符串开头添加另一特殊符号,比如$#a#b#a#。 以字符串3212343219为例,处理后变成S[] = "$#3#2#1#2#3#4#3#2#1#9#"。 然后用一个数组Len[i]来记录以字符S[i

AC,∑ndless 4609

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Manacher算法 O(n) 求最长回文子串

本文转自:http://bbs.dlut.edu.cn/bbstcon.php?board=Competition&gid=23474 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长, 这个算法有一个很巧妙的地方,它把奇数的回文...

weixin_30918415的博客 87

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

poj 3974 史上最NB 求最长回文子串 O(N) Manacher算法

/* Manacher算法--O(n)回文子串算法 OTL(好牛B的算法啊) O(n)求最长回文子串 p[i]-1为新串以str[i]为中心的最大回文长度,以#为中心则回文串长度为偶数,否则为奇数 */ #include #include #include #include #define Maxn 1000100 using namespace std; char

天逸南爵的专栏 1109

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

求字符串的最长回文子串(manacher算法O(n)时间)

题目描述小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”小Ho奇怪的问道:“什么叫做最长回文子串呢?”小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是124

Daioo 随笔 306

[hdu3068 最长回文]Manacher算法,O(N)求最长回文子串

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文串并更新答案,复杂度O(N3)。 枚举回文串的对称轴i,以及回文半径r,由i和r可确定一个子串,然后暴力判断即可。复杂度O(N2)。 在上一步的基础上,改进判断子串是否是回文串...

weixin_30433075的博客 115

Manacher算法: O(n)时间求字符串的最长回文子串

转载自 http://www.felix021.com/blog/read.php?2040 (这篇文章挺不错的,对于P数组边界问题的理解还有不清楚的,这里还有一篇:http://blog.youkuaiyun.com/hopeztm/article/details/7932245) 源于这两篇文章:  http://blog.youkuaiyun.com/ggggiqnypgjg/article/de

闲停 892

Manacher算法: O(n)时间求字符串的最长回文子串

回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了。算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p[ i ]记录以 str[ i ] 为中间字符的回文串向右能匹配的长度。先看个例子 原串:w a a b w s w f d 新串: # w # a # a # b # w # s # w

Fighting 766

hiho#1032 : 最长回文子串 (manacher算法O(n)时间求字符串的最长回文子串 )

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述    小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。    这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符

苏苏爱自由 4925

O(n)的方法求最长回文子串长度(Manacher算法)

O(n)求最长回文子串

ddjing_的博客 309

求最长回文子串的Manacher算法,time O(n)

来源: http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html http://www.felix021.com/blog/read.php?2040

jinshandayouxia的专栏 434

2.4 Manacher‘s ALGORITHM(马拉车算法): O(n)复杂度求字符串的最长回文子串

/*算法功能:奇数串最长回文串长度-Manacher算法(马拉车算法) 思路:1.转换原始串字符个数为奇数个(2n+1个):int INIT(char *st) 2.计算所有字符的回文半径(mx-前面计算回文串最右位置,po-最右位置对应中心下标); 3.最长回文长度=max(回文半径)-1 调用:scanf("%s",str); int len = INIT(str); printf("%d\n",MANACHER(tmp,len)); @param:char *st-转换后字符数组,le...

huangxl1991的博客 210

字符串——求最大回文子串——Manacher算法

1. Manacher 算法 Manacher算法主要用于处理字符串中求最长回文子串问题的算法。 传统的求最长回文子串算法,是先确定一个轴, 然后以该轴为中心向两边遍历判断是否相等,从而得到以该轴为中心最大回文子串,近而获取该字符串的最大回文子串。其时间复杂度为O(n^2)。效率低,而且还要分类处理奇偶长度的回文串。 所以一个叫Manacher的人发明了一个算法,即Manacher算法,将时间复杂...

weixin_43326910的博客 525

串子串Manacher算法: O(n)时间求字符串的最长回文子串

今天个人几篇文章介绍了改串子串的文章. 关联文章的地址               回文串包含奇数长的和偶数长的,一般求的时候都要分情况论讨,这个法算做了个单简的处置把奇偶情况一统了。法算的基本思路是这样的,把原串个每字符间中用一个串中没涌现过的字符分开开来(一统奇偶),用一个数组p[ i ]记载以 str[ i ] 为间中字符的回文串向右能配匹的度长。先看个例子      原串:w  a...

weixin_34248258的博客 96
上一篇: hdu 2222 Keywords Search (AC自动机-初步-很理解!)
下一篇: hdu 3068 最长回文 (Manacher O(n) ) (扩展KMP和后缀数组也都可以做 O(nlogn))
aclay
博客等级 码龄15年 37粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值