题目链接

manacher算法:在线性时间内求一个字符串中所有/最长回文串的算法。

先来考虑一下暴力的算法,枚举每个中点,向两边扩展,时间复杂度\(O(n^2)\)。

来分析下此算法的缺点。

1、因为回文串有奇偶之分,所以要分类讨论,\(abba\)的对称轴不在字符上,分类讨论就会有点麻烦。

为此,\(manacher\)算法的解决方案是在每个字符之间插入一个相同的字符,比如说\(\#\),

\(ababa->\#a\#b\#a\#b\#a\#\),这样就不用考虑回文串的奇偶性了。

2、效率低。为什么低?每个位置会被重复遍历。和\(KMP\)算法类似,\(manacher\)也是利用已有信息减少重复无用操作。

比如说\(abacaba\),这是一个回文串,但两边的\(aba\)也都是一个回文串,我们在枚举到右边的\(b\)时就已经能确定已这个\(b\)为中心的回文串的回文半径至少为\(2\),然后直接从这个长度开始拓展就好了。设\(hw[i]\)表示以\(a[i]\)为回文中心的回文半径长度,\(maxright\)表示当前已发现的右端点最右的右端点,\(mid\)表示这个回文串的中心。

则有如下算法(我觉得看代码比看讲解容易懂些)

for(int i = 1; i < len; ++i){
if(i < maxright)
hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i); //min左边的参数是这个点的对称点的hw值,右边的是保证这个部分在这个大回文串之内
else hw[i] = 1;
while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i]; //拓展
if(hw[i] + i > maxright){ //更新右端点
maxright = hw[i] + i;
mid = i;
}
}

该题完整代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 11000010;
char b[MAXN], a[MAXN << 1];
int hw[MAXN << 1], ans, n;
int main(){
scanf("%s", b);
a[0] = a[1] = '#';
int len = strlen(b);
for(int i = 0; i < len; ++i)
a[(i << 1) + 2] = b[i], a[(i << 1) + 3] = '#';
int maxright = 0, mid; len = (len << 1) + 3;
for(int i = 1; i < len; ++i){
if(i < maxright)
hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i);
else hw[i] = 1;
while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i];
if(hw[i] + i > maxright){
maxright = hw[i] + i;
mid = i;
}
ans = max(ans, hw[i] - 1);
}
printf("%d\n", ans);
return 0;
}

【洛谷 P3805】 【模板】manacher算法的更多相关文章

  1. 洛谷P3805 [模板]Manacher算法 [manacher]

    题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...

  2. 洛谷.3805.[模板]manacher算法

    题目链接 之前做很早了没写这篇,补上. 记录当前ex[]最大的回文中心id和最远延伸范围mx! 关于串的构造: 应该是 @ #A#B#C#B#A# $ ,而不是 @ A#B#C#B#A $ 比如 @a ...

  3. 洛谷 P3805 【模板】manacher算法

    洛谷 P3805 [模板]manacher算法 洛谷传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入格式 一行小写英文字符 ...

  4. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  5. 洛谷 P3805【模板】manacher算法

    题目链接:https://www.luogu.com.cn/problem/P3805 Manacher算法$O(n)$: 求以每个字符为中心的最长回文串的半径:如果要求可以以字符间隙为回文中心,就要 ...

  6. [洛谷P3805]【模板】manacher算法

    题目大意:给你一个字符串,求出它的最长回文字段 题解:$manacher$算法 卡点:$p$数组未开两倍空间 C++ Code: #include <cstdio> #include &l ...

  7. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  8. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  9. 【AC自动机】洛谷三道模板题

    [题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...

随机推荐

  1. 一步一步构建手机WebApp开发——环境搭建篇

    从2007年,乔布斯带来了第一代Iphone手机,整个移动互联网发生天翻地覆的变化,也同时证明了乔布斯的一句名言:“再一次改变世界”. 在当今的移动互联网,手机App居多,很多App对移动设备的要求也 ...

  2. 获取.jar文件运行时所处的路径

    在Windows控制台中运行.jar文件时的两种环境: (1)控制台当前所在目录是.jar文件所在的目录 (2)控制台当前所在目录不是.jar文件所在的目录 我的期望: 我希望在上述两种环境下均可以得 ...

  3. jenkins使用Role Strategy管理用户权限

    下载插件地址:https://wiki.jenkins.io/display/JENKINS/Role+Strategy+Plugin 1. 安装好插件后,进入jenkins系统管理的Configur ...

  4. (原)Android到IOS开发的转换(一)

    序)闲扯几句 很早就想入手ios开发,但是一直没有机会,个人没有水果机器,上个公司上班的那台mac mini虽然就在我身边,灰都有一层了,但是一直没有机会开机学习下,因为事多,自上一篇文章后,离职后, ...

  5. [转][赞]Android开发者必知的开发资源

    英文原文:Bongzimo  翻译: ImportNew-黄小非 随着Android平台市场份额的持续猛增 ,越来越多的开发者开始投入Android应用程序的开发大潮.如果您是一位2013年刚刚入行的 ...

  6. 接口测试工具postman(一)下载安装说明

    Postman是Google开发的一款功能强大的网页调试与发送网页HTTP请求,并能运行测试用例的的Chrome插件. 主要功能包括: 1.模拟各种HTTP requests 从常用的 GET.POS ...

  7. CSS3 : box-shadow

    box-shadow 用于设置边框阴影,语法: box-shadow: h-shadow v-shadow blur spread color inset; -moz-box-shadow: h-sh ...

  8. CodeForces-1132F Clear the String

    题目链接 https://vjudge.net/problem/CodeForces-1132F 题面 Description You are given a string \(s\) of leng ...

  9. Tensorflow多线程输入数据处理框架

    Tensorflow提供了一系列的对图像进行预处理的方法,但是复杂的预处理过程会减慢整个训练过程,所以,为了避免图像的预处理成为训练神经网络效率的瓶颈,Tensorflow提供了多线程处理输入数据的框 ...

  10. 常见 SQL语句使用 增删改查

    一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...