马拉车——Manacher一篇看上去很靠谱的理解(代码显然易懂)
由于回文分为偶回文(比如 bccb)和奇回文(比如 bcacb),而在处理奇偶问题上会比较繁琐,所以这里我们使用一个技巧,在字符间插入一个字符(前提这个字符未出现在串里)。举个例子:s="abbahopxpo"
,转换为s_new="$#a#b#b#a#h#o#p#x#p#o#"
(这里的字符 $ 只是为了防止越界,下面代码会有说明),如此,s 里起初有一个偶回文abba
和一个奇回文opxpo
,被转换为#a#b#b#a#
和#o#p#x#p#o#
,长度都转换成了奇数。
定义一个辅助数组int p[]
,p[i]
表示以s_new[i]
为中心的最长回文的半径,例如:
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
s_new[i] | $ | # | a | # | b | # | b | # | a | # | h | # | o | # | p | # | x | # | p | # |
p[i] | 1 | 2 | 1 | 4 | 5 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 6 | 1 | 2 | 1 |
可以看出,p[i]-1
正好是原字符串中最长回文串的长度。
Manacher 算法之所以快,就快在对 p 数组的求法上有个捷径,看下图:
设置两个变量,mx 和 id 。
mx 代表以s_new[id]
为中心的最长回文最右边界,也就是mx=id+p[id]
。
假设我们现在求p[i]
,也就是以s_new[i]
为中心的最长回文半径,如果i<mx
,如上图,那么:
if (i < mx)
p[i] = min(p[2 * id - i], mx - i);
2 * id -i
其实就是等于 j ,p[j]
表示以s_new[j]
为中心的最长回文半径,见上图,因为 i 和 j 关于 id 对称,我们利用p[j]
来加快查找。
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std; char s[];
char s_new[];
int p[]; int Init()
{
int len = strlen(s);
s_new[] = '$';
s_new[] = '#';
int j = ; for (int i = ; i < len; i++)
{
s_new[j++] = s[i];
s_new[j++] = '#';
} s_new[j] = '\0'; //别忘了哦 return j; //返回s_new的长度
} int Manacher()
{
int len = Init(); //取得新字符串长度并完成向s_new的转换
int maxLen = -; //最长回文长度 int id;
int mx = ; for (int i = ; i < len; i++)
{
if (i < mx)
p[i] = min(p[ * id - i], mx - i); //需搞清楚上面那张图含义, mx和2*id-i的含义
else
p[i] = ; while (s_new[i - p[i]] == s_new[i + p[i]]) //不需边界判断,因为左有'$',右有'\0'
p[i]++; //我们每走一步i,都要和mx比较,我们希望mx尽可能的远,这样才能更有机会执行if (i < mx)这句代码,从而提高效率
if (mx < i + p[i])
{
id = i;
mx = i + p[i];
} maxLen = max(maxLen, p[i] - );
} return maxLen;
} int main()
{
while (printf("请输入字符串:\n"))
{
scanf("%s", s);
printf("最长回文长度为 %d\n\n", Manacher());
} return ;
}
马拉车——Manacher一篇看上去很靠谱的理解(代码显然易懂)的更多相关文章
- Maven系列第6篇:生命周期和插件详解,此篇看过之后在maven的理解上可以超越同级别90%的人!
maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能. 这是maven系列第6篇. 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部 ...
- 回调函数通俗解析(之前看了很久都不理解,今天终于ok啦)
自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函数了.不懂啊,于是在google回调函数,发现网上的中文解释实在是 ...
- HDU - 3068 最长回文(马拉车Manacher)题解
思路:马拉车裸题,我们用一个p[i]数组代表以i为中心的最大回文半径.这里用了一个小技巧,如果一个串是aaaa这样的,那我们插入不相干的字符使它成为#a#a#a#a#,这样无论这个串是奇数还是偶数都会 ...
- 鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 百篇博客分析OpenHarmony源码 | v41.03
百篇博客系列篇.本篇为: v41.xx 鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...
- x01.os.15: 看上去很美
张碧晨在韩国学的不是技巧,而是基本功:气息!声音由气息托着,似真声而不是真声,似假声又不是假声,所以才能在动听的地方唱得更动听.编程也是一样,基本功很重要:内存!所谓的黑客高手,攻击的一大手段,便是利 ...
- 看上去很美 国内CDN现状与美国对比
CDN的理想与现实 多年以前,当<Kingdom of Heaven>这部史诗电影发行的时候,中国的影迷使用电驴和BT来寻找种子,而那个时候,高清也才刚刚进入电影领域,我的同事不惜用自家的 ...
- 你只是看起来很努力(只是做了一遍真题,草草的对了一遍答案,然后冲出自习室继续她学生会的事情了,骗自己更容易)good——想起了自己在六大时候的无奈
(转)你只是看起来很努力一次上课,一个女孩子垂头丧气的跟我说,老师,我考了四次四级,还没过,究竟是为什么. 我说,你真题做了吗?单词背了吗?她拿出已经翻破了的真题,跟我说,你讲的所有的题目我连答案都记 ...
- Spring Boot 揭秘与实战(四) 配置文件篇 - 有哪些很棒的特性
文章目录 1. 使用属性文件2. YAML文件 1.1. 自定义属性 1.2. 参数引用 1.3. 随机数属性 1.4. application-{profile}.properties参数加载 3. ...
- 美国诚实签经验——中英文行程单、往返机票、用英语面试的申请者通过率>用中文面试的申请者的通过率、一直保持着微笑,看上去很自信,也很诚恳、户口簿带上最好
在排队等待时据我的观察,用英语面试的申请者通过率>用中文面试的申请者的通过率.一家人申请通过率>单个人通过率:商务签证通过率>旅游签证通过率 一. 面签材料 1. 必备材 ...
随机推荐
- ABAP发邮件函数
步骤: 一.检查输入参数, (1)未指定文件類別代碼,(2)未指定郵件主題, (3)未指定郵件內容, (4)未指定發送人郵件地址, (5)未指定接收人郵件地址, 二.调用发送功能, (1)创建发送请求 ...
- DES算法解析
DES算法 美国国家标准局1973年开始研究除国防部外的其它部门的计算机系统的数据加密标准,于1973年5月15日和1974年8月27日先后两次向公众发出了征求加密算法的公告. 1977年1月,美国 ...
- Loadrunder脚本篇——Run-time Settings之Browser Enmulation
浏览器模拟 所有Internet Vuser Header包含一个标识将被模拟的浏览器类型(或无线工具包)的User Agent header.例如User-Agent: Mozilla/3.01Go ...
- SpringBoot编辑代码时不重启服务
@SpringBootApplication @ComponentScan("com.sicdt") public class SicSignWebApplication { pu ...
- 更改计算机名称,影响TFS之前映射的工作区 使用。
今天把自己电脑的计算机名称改了,打开vs2012的时候,就提示以下的错误: ---------------------------Microsoft Visual Studio------------ ...
- libhdfs的配置和使用
测试环境:centos6.10,hadoop2.7.3,jdk1.8 测试代码:HDFSCSample.c #include "hdfs.h" #include <strin ...
- 大数据架构之:Kafka
Kafka 是一个高吞吐.分布式.基于发布订阅的消息系统,利用Kafka技术可在廉价PC Server上搭建起大规模消息系统.Kafka具有消息持久化.高吞吐.分布式.多客户端支持.实时等特性,适用于 ...
- win7 与 Ubuntu 16.04 文件传送
win7 与 Ubuntu 16.04 文件传送 环境:主机系统为win7,虚拟机为vmware12, 虚拟系统为ubuntu 16.04 方案一: 通过虚拟机vmware的共享文件夹实现. 方案二: ...
- java写出图形界面
1. 做出简单的窗体 package javaGUI; import java.awt.BorderLayout; import java.awt.Color; import javax.swing. ...
- 去除带有iframe页面中的2个滚动条[转]
方法一:加载frame时修改高度 <div> <iframe id="frame_content" name="frame_content&quo ...