题解 P3805 【【模板】manacher算法】
题解 P3805 【【模板】manacher算法】
我们先看两个字符串:
ABCCBA
ABCDCBA
显然这两字符串是回文的
然而两个串的对称中心的特性不同,第一个串,它的对称中心在两个C中间,然而第二个串,它的对称中心就是D。这样我们如果要记录回文串的对称中心,就显得复杂了。
为了解决这个问题,把两种情况统一起来,我们就在字母之间插入隔板,这样两个问题就统一了,因为所有的对称中心都会有个字符与之对应。像这样
~A|B|C|C|B|A|
(注意到我们这里还插入了一个“~”,原因我们待会说明)
manacher为什么有如此优秀的复杂度呢?让我用比图片还要清楚的文字说明一下
对于一个回文串,有且仅有一个对称中心。且叫它回文对称中心。
在一个回文串内,任选一段区间 X ,一定存在关于”回文对称中心“对称的一个区间,且把这个区间叫做关于区间_X_的对称区间。
区间和对称区间一定全等。( 1)(十分显然)
由_(1)得 ,若一个区间的对称区间是回文串,这个区间必定是一个回文串。在大的回文串内,它们回文半径相等。 (2)_
然而我们通过确定关系预先得到的回文半径,它的数值,必定小于等于这个位置真实的回文串半径。(十分显然)
因此,为利用特性(2),我们若记录每个字符作为回文对称中心时的回文串的半径,就可以知道该字符,它,关于某另一个对称中心(称此对称中心对应的回文串叫做“大回文串“)对称的,在大的回文半径内,对应字符的部分回文半径了。
记录这些数据到p数组。同时记录一个mid,一个r,分别代表 已经确定的右侧最靠右的回文串的对称中心和右边界
然而,考虑一些情况,发现我们只能确认我们已知的回文串内的对称关系和回文半径等量关系,关于这个大回文串右侧的世界,我们一无所知。
那么,当我们扫描到一个新的字符时,怎么先确定它的部分回文半径呢?
若当前扫描到的位置为i,若mid<=i<=r,则我们可以找到它的一个对称点。这个点的位置是多少?是mid×2-i。我们现在对其推导一下。
设:这个新点位置为i,它关于mid对称的点为j,将整个字符串看做以下标0位置为原点的数轴,我们由中点公式可得:
( i + j ) / 2 = mid
方程两边同时乘以二, 得:
i + j = 2 * mid
移项, 得:
j=2*mid-i
证毕。
就是这样小学生都会的推导过程,几乎每篇题解都是 直接摆出结论 ,不给出证明和推导,要求学习者自己”找规律” , 我真是不敢苟同。希望大家以后发题解要严谨一点,至少自己没有真正理解就不要发题解,让人觉得manacher是难以学习的算法。至少当我在学习的时候,是一头雾水。
所以,拓展一个新点时,我们不必从这个点左右两边第一个位置开始向两边拓展,可以预先确定一部分回文串。就是因为这个,manacher的复杂度是线性的。
若扩展一个新的关于该字符的回文半径,可以先确定一部分P[i]。
且我们知道,我们能确定的范围,其右侧不得大于r,即:p[i]+i<=r 移项得:p[i] <= r-i
故此,要取一个min 这里给出代码:
P[i]=min(P[mid*2-i],r-i)
最终答案是
P(max)-1
讲到这里,应该十分清楚了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=11000002;
char data[maxn<<1];
int p[maxn<<1];
int cnt=1;
#define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++)
inline void qr(){
char c=getchar();
data[0]='~';
data[1]='|';
while(c<'a'||c>'z')
c=getchar();
while(c>='a'&&c<='z'){
data[++cnt]=c;
data[++cnt]='|';
c=getchar();
}
return;
}
int maxans,rb,mid;
inline int cmpless(int x,int y){
if(x<y)
return x;
return y;
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
qr();
RP(t,1,cnt){
if(t<rb)
p[t]=cmpless(p[(mid<<1)-t],rb-t);
else
p[t]=1;
while(data[t-p[t]]==data[t+p[t]])
//暴力拓展左右两侧,当t-p[t]==0时,由于data[0]是'~',自动停止。
//故不会下标溢出。
p[t]++;
if(p[t]+t>rb)
//更新mid和rb,保持rb是最右的才能保证我们提前确定的部分回文半径尽量多。
rb=p[t]+t,mid=t;
if(p[t]>maxans)
maxans=p[t];
}
cout<<maxans-1<<endl;
return 0;
}
祝大家学习愉快
题解 P3805 【【模板】manacher算法】的更多相关文章
- 洛谷P3805 [模板]Manacher算法 [manacher]
题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...
- 模板 manacher算法
题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符串S 输出格 ...
- 洛谷.3805.[模板]manacher算法
题目链接 之前做很早了没写这篇,补上. 记录当前ex[]最大的回文中心id和最远延伸范围mx! 关于串的构造: 应该是 @ #A#B#C#B#A# $ ,而不是 @ A#B#C#B#A $ 比如 @a ...
- 洛谷 P3805 【模板】manacher算法
洛谷 P3805 [模板]manacher算法 洛谷传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入格式 一行小写英文字符 ...
- [洛谷P3805]【模板】manacher算法
题目大意:给你一个字符串,求出它的最长回文字段 题解:$manacher$算法 卡点:$p$数组未开两倍空间 C++ Code: #include <cstdio> #include &l ...
- Manacher || Luogu P3805【模板】manacher算法
题面:[模板]manacher算法 代码: #include<cstdio> #include<cstring> #include<iostream> #defin ...
- 洛谷 P3805【模板】manacher算法
题目链接:https://www.luogu.com.cn/problem/P3805 Manacher算法$O(n)$: 求以每个字符为中心的最长回文串的半径:如果要求可以以字符间隙为回文中心,就要 ...
- 【洛谷 P3805】 【模板】manacher算法
题目链接 manacher算法:在线性时间内求一个字符串中所有/最长回文串的算法. 先来考虑一下暴力的算法,枚举每个中点,向两边扩展,时间复杂度\(O(n^2)\). 来分析下此算法的缺点. 1.因为 ...
- P3805 【模版】manacher算法(manacher)
P3805 [模版]manacher算法 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a ...
随机推荐
- Java NIO中的FileLock(文件锁)
FileLock,文件锁. 文件锁在OS中很常见,如果多个程序同时访问.修改同一个文件,很容易因为文件数据不同步而出现问题.给文件加一个锁,同一时间,只能有一个程序修改此文件,或者程序都只能读此文件, ...
- PHP如何在页面中原样输出HTML代码
字符串与HTML之间的相互转换主要应用htmlentities()函数来完成. header("Content-Type: text/html; charset=utf-8"); ...
- REMOTE HOST IDENTIFICATION HAS CHANGED 问题解决
今天处理 ssh连接至 ubuntu 服务器时,提示以下错误: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING ...
- 优化算法——拟牛顿法之L-BFGS算法
一.BFGS算法 在"优化算法--拟牛顿法之BFGS算法"中,我们得到了BFGS算法的校正公式: 利用Sherman-Morrison公式可对上式进行变换,得到 令,则得到: 二. ...
- HTML5 Canvas 绘制星条旗
代码: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type ...
- base64加密PHP脚本的解码方法
转自:http://yoursunny.com/t/2009/PHP-decode/ PHP是网站服务端最流行的编程语言之一.PHP运行环境本身是开源的,服务器不加载插件时PHP脚本也无法加密.但是, ...
- 分层架构web容器的配置安全
转自:http://hi.baidu.com/shineo__o/item/7520d54c24d234c71081da82 /ps:本以为这是一个偶然配置失误造成的问题,但最近几天无聊时测试发现,有 ...
- Jackson.jar的使用记录
Jackson.jar的使用记录 之前一直使用json-lib.jar,近期发现网上说这个jackson.jar比較好 package com.spring.controller; import ja ...
- JQuery EasyUI DataGrid动态合并单元格
/** * EasyUI DataGrid根据字段动态合并单元格 * @param fldList 要合并table的id * @param fldList ...
- C# 字节数组拼接的速度实验(Array.copy(),Buffer.BlockCopy(),Contact())
无聊做了如题的一个算法的优劣性能比较,由于很多人都只关心结果,那么我先贴出结果如下: 由于我的测试数据量比较小,只能得出Array.Copy()和Buffer.BlockCopy()方法性能要好于Co ...