[最长回文字符串]manacher马拉车
manacher马拉车 https://www.luogu.com.cn/problem/P3805
闲言一下:花了一个中午终于把 manacher 给搞懂了。本文将以一个蒟蒻的身份来,来写写马拉车算法。首先请自行回顾暴力的 最长回文字符串 算法。首先我们将 通过枚举中心点,并扩展以该中心点为回文中心的回文串长度的算法称为 “中心扩展法”。manacher算法便是以“中心扩展法”为核心,利用枚举中获取的信息优化而来的。
具体地来说:
首先在解决奇偶回文字符串时,我们使用分类讨论的方法,解决了奇数和偶数的问题,但是这样未免过于麻烦,有什么可以将二者统一的方式呢?
这是处理前的字符串
具体地来说:
首先在解决奇偶回文字符串时,我们使用分类讨论的方法,解决了奇数和偶数的问题,但是这样未免过于麻烦,有什么可以将二者统一的方式呢?
这是处理前的字符串
a b b c
1 2 3 4
这是处理后的字符串
# a # b # b # c #
1 2 3 4 5 6 7 8 9
我们通过加字符的方法,注意这里不一定要是 # ,也可以是其他字符,主要目标是为了将奇偶回文字符串统一了起来。这样在处理回文字符串时,会更加的方便。(不过也容易犯一些粗心的小问题,这些问题会在文章末尾提及)。
接下来回想一下 中心扩展法 求解最长回文序列的时候。遇到这种情况时
a b a d a b a
1 2 3 4 5 6 7
当我们枚举完 以下标为 4 的点为中心时,我们可以知道 1~7 为回文序列。加上前面以下标为3的点为中心时,我们可知道 1~3 为回文序列。根据回文序列的对称性,我们可以得出 5~7 也为回文序列。但在我们使用中心扩展法时,就需要多余地去枚举以下标为3的点为中心的回文半径的长度。这大大地浪费了时间。因此我们可以从这个角度入手,优化我们的算法。
从 中心扩展法 的基础上,再根据刚刚从特殊数据的角度,我们可以想到先定义几个变量maxr,mid ,用来表示当前已知的回文序列中最右的右端点,及该回文序列的中点。为什么要记录最右的右端点呢?因为右端点越右的回文序列就越容易包括后面还未遍历的中心,这样就能尽可能的达到,通过现有信息尽可能减少多余遍历的目的了。再定义一个数组 p[i] 表示以 i 为中点的回文序列的回文半径。
具体来讲一下优化的要点,
情况一
a b b c
1 2 3 4
这是处理后的字符串
# a # b # b # c #
1 2 3 4 5 6 7 8 9
我们通过加字符的方法,注意这里不一定要是 # ,也可以是其他字符,主要目标是为了将奇偶回文字符串统一了起来。这样在处理回文字符串时,会更加的方便。(不过也容易犯一些粗心的小问题,这些问题会在文章末尾提及)。
接下来回想一下 中心扩展法 求解最长回文序列的时候。遇到这种情况时
a b a d a b a
1 2 3 4 5 6 7
当我们枚举完 以下标为 4 的点为中心时,我们可以知道 1~7 为回文序列。加上前面以下标为3的点为中心时,我们可知道 1~3 为回文序列。根据回文序列的对称性,我们可以得出 5~7 也为回文序列。但在我们使用中心扩展法时,就需要多余地去枚举以下标为3的点为中心的回文半径的长度。这大大地浪费了时间。因此我们可以从这个角度入手,优化我们的算法。
从 中心扩展法 的基础上,再根据刚刚从特殊数据的角度,我们可以想到先定义几个变量maxr,mid ,用来表示当前已知的回文序列中最右的右端点,及该回文序列的中点。为什么要记录最右的右端点呢?因为右端点越右的回文序列就越容易包括后面还未遍历的中心,这样就能尽可能的达到,通过现有信息尽可能减少多余遍历的目的了。再定义一个数组 p[i] 表示以 i 为中点的回文序列的回文半径。
具体来讲一下优化的要点,
情况一

如果是上图的这种情况,则p[i]=p[j] , j=mid-(i-mid) --> j=2*mid-i 。(回文序列的对称性)
情况二
如果是上图的这种情况,则不一定p[i]=p[j] ,因为超过ml ~ mr的部分并不满足回文序列的性质。所以只有在ml ~ mr的部分才能进入计算,因此p[i]=mr-i+1 。
重要的优化只有这些,其他的和 中心扩展法的做法大致相同。
#include<bits/stdc++.h>
using namespace std;
const int N=9*1e7;
string str="!#",c;/*为什么第一位是“!”?
为了避免程序第16行扩展时越界 */
int p[N],mid=0,mr=0,ans;
void work(){
cin>>c;
for(int i=0;c[i]>='a'&&c[i]<='z';i++){
str+=c[i];
str+='#';
}/*处理原序列*/
for(int i=1;i<str.size();i++){
if(i<=mr) p[i]=min(p[2*mid-i],mr-i+1);
/*i关于mid对称点; mid-(i-mid)——> 2*mid-i */
while(str[i-p[i]]==str[i+p[i]]) p[i]++;
//这里其实就是扩展 回文序列的 回文半径
if(i+p[i]>mr){
mid=i;
mr=i+p[i]-1;
}
if(p[i]>ans) ans=p[i];
}
cout<<ans-1;
}
int main(){
work();
return 0;
}
粗心的小问题(建议自行写完代码后查看)
1.因为要插入一堆字符,所以字符数组和其他相关数组的大小需要翻倍
[最长回文字符串]manacher马拉车的更多相关文章
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- 【转载】最长回文字符串(manacher算法)
原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- 最长回文子串 —— Manacher (马拉车) 算法
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- hdu3068 求一个字符串中最长回文字符串的长度 Manacher算法
最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...
- hdu----(3068)最长回文(manacher)
最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 最长回文子串——manacher
最长回文子串--Manacher 算法 (原版的博主的代码都是用py写的,这里改成c++) c++ 算法 字符串处理 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一 ...
- JavaScript之最长回文字符串
JavaScript经典面试题算法:最长回文字符串 下面的解题方法是通过中心扩散法的方式实现的,具体代码和注释如下(时间复杂度: O(n^2),空间复杂度:O(1)) // str字符串functio ...
- leetcode5 最长回文字符串 动态规划 Manacher法
dp 注意没有声明S不空,处理一下 o(n^2) class Solution { public: string longestPalindrome(string s) { if (s.empty() ...
随机推荐
- 记录 跨境猴 shopee 虾皮 货代 贴单 仓储 打包系统 介绍
shopee虾皮|lazada|shopify代打包贴单仓储系统(简称:跨境猴)基于ThinkPHP6.0+AdminLTE-2.3.11+JQuery+PHP7.0+Swoole+Mysql5.5+ ...
- 谈一谈Python中的装饰器
1.装饰器基础介绍 1.1 何为Python中的装饰器? Python中装饰器的定义以及用途: 装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数.装饰器可以用来修改或增强函数的行 ...
- Arrays.asList() 示例
1 package Test.others; 2 3 import java.util.Arrays; 4 import java.util.Collections; 5 import java.ut ...
- [Pytorch框架] 2.1.4 数据的加载和预处理
文章目录 PyTorch 基础 :数据的加载和预处理 Dataset Dataloader torchvision 包 torchvision.datasets torchvision.models ...
- PaddlePaddle 飞桨复现 VGG16
import paddle.nn as nn class VGG16(nn.Layer): def __init__(self, num_classes=1000): super(VGG16, sel ...
- 2022-11-24:小团在地图上放了3个定位装置,想依赖他们进行定位! 地图是一个n*n的棋盘, 有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内。 小团在(a,
2022-11-24:小团在地图上放了3个定位装置,想依赖他们进行定位! 地图是一个n*n的棋盘, 有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内. 小团在(a, ...
- 2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数的最大差值。要求:时间复杂度O(N) 。
2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数的最大差值.要求:时间复杂度O(N) . 福大大 答案2021-05-20: 假设答案法.N个数,根据最大值和最小值的范围等分成N ...
- 2021-10-20:分数到小数。给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。输入: num
2021-10-20:分数到小数.给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数.如果小数部分为循环小数,则将循环的部分括在括号内.输入: num ...
- operation not supported on selected printer
operation not supported on selected printer 版本原因 解决办法, 每次打印前先选择一次打印机属性,弹窗点确认还是取消都行,最后返回再点打印即可
- [SWPUCTF 2021 新生赛]no_wakeup
[SWPUCTF 2021 新生赛]no_wakeup 考点 反序列化 一.题目 打开题目发现如下代码 <?php header("Content-type:text/html;cha ...