Algorithm

Task

给定一个字符串,求其最长回文子串

Limitations

要求时空复杂度均为线性且与字符集大小无关。

Solution

考虑枚举回文串的对称轴,将其对应的最长回文子串长度 \(len\) 求出来,取最大值即为答案。

首先回文串有两种,长度为奇数的和长度为偶数的,第一种的对称轴是一个字符,第二种的对称轴在两个字符之间。

为了将两种情况统一起来,我们将原字符串的每两个相邻字符之间和首位字符前后都加上同一个不在字符集内的其他字符,例如,将 \(aaa\) 变成 \(\#a\#a\#a\#\),这样字符串的对称轴一定是一个字符了。

定义回文半径 \(r\) 为对称轴到回文串边界的字符数量,也即对称轴的下标,考虑新字符串的回文半径一定是 # 和其他字符交替出现,并以 # 结尾,因此 r 一定是奇数,而其中真正的的字符数量为 \(\frac{r - 1}{2}\),加上另一侧得字符,得到该回文串对应原字符串的回文长度为 \(\frac{r - 1}{2} \times 2~=~r - 1\)。

我们从左到右扫描新字符串,设当前扫描到了 \(i\),则 \(\forall j \in [1, ~i)\),\(len_j\) 已经被计算完毕。

设之前的所有回文子串中,右端点最大的为 \(pos\),其对应对称轴为 \(mid\)。

分两种情况讨论。

第一种情况,\(i < pos\),则 \(i\) 在以 \(pos\) 为右端点,$ mid$ 为对称轴的大回文串中。

找到 \(i\) 关于 \(mid\) 的对称点 \(j\) ,若 \(j\) 对应的回文串的左端点不在大回文串的左侧,由于回文串的对称性,对称过去以后 \(i\) 的对应回文串应该与 \(j\) 相同,于是有 \(len_i = len_j\)。

否则,在回文串内部的部分一定是对称的,对于 \(pos\) 右侧的部分,则暴力向右匹配即可。

第二种情况,\(i \geq pos\),则直接进行暴力匹配。

考虑复杂度:每次暴力匹配,\(pos\) 会自增 \(1\),而单次的复杂度是 \(O(1)\) 的,因此暴力匹配的总复杂度是 \(O(|S|)\) 的,而剩下的操作都是 \(O(1)\) 的因此总的时间复杂度是线性的。

Sample

P3805 【模板】manacher算法

Description

给定一个只由小写字母组成的回文串 \(S\),求最长回文子串长度。

Limitations

\(|S| \leq 1.1 \times 10^7\)

Solution

板板题,依然需要注意等号的位置。

在实现中,可以在字符串结尾添加另一个无关字符,这样可以保证匹配时不会越界,并且不用手动判断。

Code

#include <cstdio>
#include <algorithm> const int maxn = 22000007; int n, ans;
char S[maxn];
int len[maxn], mid[maxn]; void ReadStr(); int main() {
freopen("1.in", "r", stdin);
ReadStr();
for (int i = 1, pos = 0; i <= n; ++i) {
if (i >= pos) {
int l = pos = i;
while (S[l - 1] == S[pos + 1]) { --l; ++pos; }
len[i] = pos - i + 1;
mid[pos] = i;
} else {
int j = (mid[pos] << 1) - i;
if (len[j] < (pos - i + 1)) {
len[i] = len[j];
} else {
int l = (i << 1) - pos;
while (S[l - 1] == S[pos + 1]) { --l; ++pos; }
len[i] = pos - i + 1;
mid[pos] = i;
}
}
ans = std::max(ans, len[i]);
}
qw(ans - 1, '\n', true);
return 0;
} void ReadStr() {
static char tmp[maxn];
int _len = 0;
do tmp[++_len] = IPT::GetChar(); while ((tmp[_len] >= 'a') && (tmp[_len] <= 'z'));
tmp[_len--] = 0;
for (int i = 1; i <= _len; ++i) {
S[++n] = '#';
S[++n] = tmp[i];
}
S[++n] = '#'; S[++n] = '$';
}

【字符串】 manacher算法的更多相关文章

  1. 第5题 查找字符串中的最长回文字符串---Manacher算法

    转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...

  2. POJ 3974 Palindrome 字符串 Manacher算法

    http://poj.org/problem?id=3974 模板题,Manacher算法主要利用了已匹配回文串的对称性,对前面已匹配的回文串进行利用,使时间复杂度从O(n^2)变为O(n). htt ...

  3. 最长回文字符串(manacher算法)

    偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述:      回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...

  4. 【转载】最长回文字符串(manacher算法)

    原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...

  5. 利用Manacher算法寻找字符串中的最长回文序列(palindrome)

    寻找字符串中的最长回文序列和所有回文序列(正向和反向一样的序列,如aba,abba等)算是挺早以前提出的算法问题了,最近再刷Leetcode算法题的时候遇到了一个(题目),所以就顺便写下. 如果用正反 ...

  6. 计算字符串的最长回文子串 :Manacher算法介绍

    转自: http://www.open-open.com/lib/view/open1419150233417.html Manacher算法 在介绍算法之前,首先介绍一下什么是回文串,所谓回文串,简 ...

  7. 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串

    1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...

  8. 【字符串算法2】浅谈Manacher算法

    [字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述  字符串算法2:Manacher算法 问题:给出字符串S(限制见后)求出最 ...

  9. 【字符串】manacher算法

    Definition 定义一个回文串为从字符串两侧向中心扫描时,左右指针指向得字符始终相同的字符串. 使用manacher算法可以在线性时间内求解出一个字符串的最长回文子串. Solution 考虑回 ...

  10. ACM -- 算法小结(八)字符串算法之Manacher算法

    字符串算法 -- Manacher算法 首先介绍基础入门知识,以下这部分来着一贴吧,由于是很久之前看的,最近才整理一下,发现没有保存链接,请原创楼主见谅. //首先:大家都知道什么叫回文串吧,这个算法 ...

随机推荐

  1. Laravel本地环境搭建:Homestead开发环境的部署

    Laravel框架在php开发过程是不断进行优化的,当然也包括了本地环境的开发,下面我们就来具体看看laravel框架中的Homestead 开发环境的部署内容. 首先白以下几个概念 VirtualB ...

  2. bizcharts 图表内容居中

    当图表内的数据只有一组时,会紧靠在y轴上,如下图: 想要图表的内容居中,解决方法分两种情况. 第一种:如果x轴是日期,则代码设置如下,图表的内容就居中了 const cols = { x: { ali ...

  3. 024 如何让html引用公共的头部和尾部(多个html文件公用一个header.html和footer.html)

    前端静态html页面,封装公共的头文件(header:顶部页眉,顶部导航栏等部分)和尾部文件(footer:CopyRight.友情链接等部分) 当前方法:通过load()函数,引入公共头部和尾部文件 ...

  4. scala中停止循环的三种方式

    1:使用return关键字 object BreakLoop { //1.使用return关键字 def add():Unit= { for(i <- 1 to 10){ if(i==7){ / ...

  5. 【问题记录】ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

    一.问题描述 环境:MySQL 8.0 + Windows 由于密码错误或者其他原因导致无法连上MySQL服务,如下图: 二.解决方案 解决该问题的具体步骤如下: 1.关闭MySQL服务 以管理员权限 ...

  6. HTML+CSS学习笔记整理

    一.标签语义化(重点): 1.可以方便代码的阅读和维护 2.同时让网络爬虫更好的解析从而更好的分析其内容 3.更好的优化引擎 如何做到标签语义化:个人理解是,首先,网页的HTML主要作用在网页的结构上 ...

  7. vue v-for 使用问题整理

    今天使用v-for指令的时候遇到一个错误 [Vue warn]: Error in render: "TypeError: Cannot read property 'children' o ...

  8. mvc中ViewBag返回数组如何循环显示数据

    直接在for循环里面定义出viewbag @for (int i = 0; i < ViewBag.permission.Count; i++) { var permission = ViewB ...

  9. 基于vue+springboot+docker网站搭建【二】搞定服务器

    搞定服务器 双11在阿里云用家人的身份证注册账号,买了两台打折的服务器.2核4G一台3年799块:1核2G一台3年229块.机器配置如下图. 1.买的时候注意相同地区的相同可用区.比如我两台机器都选择 ...

  10. 基于Custom-metrics-apiserver实现Kubernetes的HPA(内含踩坑)

    前言 这里要说一下Prometheus的检控指标从哪里来,它有3个渠道: 主机监控,也就是部署了Node Exporter组件的主机,它以DaemonSet或者系统进程的形式运行,Prometheus ...