[最长回文字符串]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() ...
随机推荐
- 从ajax到跨域引发的相关面试题总结
转载请注明出处: 1.ajax异步和同步的区别 Ajax是一种基于JavaScript语言和XMLHttpRequest对象的异步数据传输技术,通过它可以使不用刷新整个页面的情况下,对页面进行部分更新 ...
- Restless API 与 Restful API
Restful API: 1.CURD(增删改查) 由请求方式决定 2.请求方式有:get/post/delete/put 3.同一个路径可以进行多个操作 Restless API 1.CURD(增 ...
- DES算法图解、密码学
- 深度学习基础5:交叉熵损失函数、MSE、CTC损失适用于字识别语音等序列问题、Balanced L1 Loss适用于目标检测
深度学习基础5:交叉熵损失函数.MSE.CTC损失适用于字识别语音等序列问题.Balanced L1 Loss适用于目标检测 1.交叉熵损失函数 在物理学中,"熵"被用来表示热力学 ...
- 23.oneOf
const { resolve } = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') // 提取cs ...
- ChatGPT最全提示词Prompts总结,看这一篇就够了!
以下几乎涵盖了各类人群想要使用ChatGPT的所有提示词,需要的朋友可以直接复制粘贴使用. 从翻译到整理耗费超过2个小时,如果内容对大家有帮助,请不要吝啬你们的喜欢.点赞.关注~ 如何正确的提问? ...
- 2023-05-08:我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符, 并返回唯一字符的个数。 例如:s = “LEETCODE“ ,则其中 “L“, “T
2023-05-08:我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符, 并返回唯一字符的个数. 例如:s = "LEETCODE" ,则 ...
- 2022-11-18:给定一个数组arr,表示连续n天的股价,数组下标表示第几天 指标X:任意两天的股价之和 - 此两天间隔的天数 比如 第3天,价格是10 第9天,价格是30 那么第3天和第9天的指
2022-11-18:给定一个数组arr,表示连续n天的股价,数组下标表示第几天 指标X:任意两天的股价之和 - 此两天间隔的天数 比如 第3天,价格是10 第9天,价格是30 那么第3天和第9天的指 ...
- 2022-09-18:以下go语言代码输出什么?A:1;B:15;C:panic index out of range;D:doesn’t compile。 package main import
2022-09-18:以下go语言代码输出什么?A:1:B:15:C:panic index out of range:D:doesn't compile. package main import ( ...
- vue全家桶进阶之路14:常用属性和方法
Vue2中常用的属性和方法: 属性 el:用于指定Vue实例挂载的元素,可以是CSS选择器.HTML元素或Vue组件. data:用于存储Vue实例的响应式数据,也可以是一个函数,返回一个对象,用于提 ...