首页 > 其他分享 >Manacher

Manacher

时间:2024-02-20 17:45:59浏览次数:17  
标签:子串 min Manacher str 区间 对称

废话

绅士曾言:哈希只比马拉车多了只 \(\log\) 而已,不用在意。

然后他写的马拉车 + 线段树 T 了,正解是使用前缀后缀记录最小最大值。

事实证明一只 \(\log\) 的复杂度优化也是必要的,所以。。。

不可能学什么后缀数组 + 快速 LCA 的。

Manacher

如何求一个字符串的最长回文子串?

首先,因为子串长度有奇有偶不便处理,所以不妨在原字符串两相邻字符之间以及两端都加上一个特殊字符。

这样我们就只用处理长度为奇数的串了。

令 \(p_{i}\) 表示以第 \(i\) 个字符为中心的最长回文子串的「半径」,假设我们已经处理好了 \(p_{1 \sim i - 1}\),如何快速求出 \(p_{i}\)?

我们知道 \([i - p_{i} + 1, i + p_{i} - 1]\) 这一段区间一定是对称的,那么可否利用「对称」这个性质来快速推导呢?

我们记录一个「最靠右」的对称区间(假设为 \([l, r]\),「最靠右」是指 \(r\) 最大),若 \(i\) 在这个区间之外,那么暴力求出 \(p_{i}\)。

若 \(i\) 在区间之内,那么说明 \(p_{i} \geqslant \min(p_{l + r - i}, r - i + 1)\),因为在这个对称区间中以 \(l + r - i\) 为中心和以 \(i\) 为中心的半径为 \(\min(p_{l + r - i}, r - i + 1)\) 的子串一定相同,并且 \(\min(p_{l + r - i}, r - i + 1) \leqslant p_{l + r - i}\) 所以这个相同子串也一定是回文串。

但是这个子串可能会因为 \(\min\) 的限制「卡」在了边界 \(r\) 处,这个时候暴力更新就好了。更新完后也要更新「最靠右」的对称区间。

因为 \(r\) 是不断增大的且最大为 \(2length + 1\),并且 \(l\) 和 \(r\) 是同时变化的,所以均摊下来的时间复杂度就是 \(\mathcal{O}(n)\)。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s, str = "V";
int n, l, r, ans, p[22000005];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> s;
	for(const auto& i : s) str.push_back(i), str.push_back('V');
	n = str.length(), l = 0, r = -1;
	for(int i = 0; i < n; ++i) {
		if(i <= r) p[i] = min(p[l + r - i], r - i + 1);
		while(i - p[i] >= 0 && i + p[i] < n && str[i - p[i]] == str[i + p[i]]) ++p[i];
		if(i + p[i] - 1 > r) l = i - p[i] + 1, r = i + p[i] - 1;
		ans = max(ans, p[i]);
	}
	cout << ans - 1;
	return 0;
}

标签:子串,min,Manacher,str,区间,对称
From: https://www.cnblogs.com/A-box-of-yogurt/p/18023665

相关文章

  • Manacher
    Manacher是找出字符串中回文子串很有效的算法具体而言,是在暴力的基础上一步步优化首先,最暴力的是\(O(n^2)\)枚举左右端点,再\(O(n)\)判断但可以直接枚举中间点,优化到\(O(n^2)\)此时出现了个问题:长度为奇数的回文串中点在中间字母,但长度为偶数的回文串中间点在空隙处!所......
  • Manacher
    ManacherManacher(马拉车)能在O(n)的时间复杂度内求出字符串中以字符i为中心的最长回文半径r[i]算法流程预处理为了避免奇偶性问题在字符串开始加上奇怪的@在字符串末尾加上&在字符中间加上#本段代码来自可爱的w++并且把他老婆inline删掉了voidInit(){scanf("%......
  • manacher
    记录23:392024-2-5manacher算法,是可以在O(n)时间计算回文串的算法具体思路可以查看Manacher非常有意思的算法。利用了俩个数组d1[i]和d2[i]分别来记录以位置i为中心的长度为奇数和长度为偶数的回文串个数这里利用了回文串个数也即以i为中心的最长回文串的半径长度(半......
  • manacher 学习笔记
    定义与基本求法定义又名马拉车,用于处理子串回文问题。基本求法暴力判断每个子串是否是回文是\(O(n^3)\)的,根据其对称性优化为\(O(n^2)\)依旧是不优秀的。马拉车便是解决这种单一问题的算法,具有局限性,但同时是解决这种问题的不二选择。枚举回文串的中点,例如\(aaba......
  • 最小表示法&Manacher学习笔记+杂题
    字符串系列前言:孩子从小就自卑。四、最小表示法&Manacher学习笔记+杂题相关题单:戳我1.最小表示法最小表示法是用于解决字符串最小表示问题的方法。(1)字符串的最小表示:字符串\(s\)的最小表示为与\(s\)循环同构的所有字符串中字典序最小的字符串。循环同构指的是当字符......
  • 最小表示法&Manacher学习笔记+杂题
    字符串系列前言:孩子从小就自卑。四、最小表示法&Manacher学习笔记+杂题相关题单:戳我1.最小表示法最小表示法是用于解决字符串最小表示问题的方法。(1)字符串的最小表示:字符串\(s\)的最小表示为与\(s\)循环同构的所有字符串中字典序最小的字符串。循环同构指的是当字符......
  • 【学习笔记】manacher
    众所周知,manacher又叫“马拉车”算法,是一种线性求解最长回文子串的算法。推荐结合模板阅读此文。求最长回文子串,首先想到的是暴力。枚举子串的左右端点\(l,r\),再判断这个子串是否回文。总复杂度\(O(n^3)\),效率过低。观察发现,我们可以只枚举中点,然后同时向左右不断扩展,当无......
  • 高铁拉我,马拉车——记高铁路上的manacher
    目录前言问题引入思路一览manacher高效的原因具体情况讨论小问题的讨论code前言不得为什么,总会在奇奇怪怪的时候特定时间看算法比平常看得舒服多了,之前看字符串匹配的时候自然是准备把马拉车一起看了的,但是那时候看不下去,昨天回家的高铁上再次看了看,觉得格外的亲切,emmm问题引入......
  • 【CF30E】Tricky and Clever Password 题解(manacher + exKMP)
    manacher+exKMP+二分。感觉是最粗暴的方法,想出来之后自己硬莽了4k,荣获题解区最长。Solution约定:下文所提及到的所有的回文串,均指奇长度回文串。显然把题目拆成两个部分,中间的回文串,以及两边相同的连续子串。考虑一下从哪个入手比较好。忘记是咋想的了,易得从两边相同......
  • Manacher与exKMP(扩展KMP,Z函数)
    Manacher算法该算法由GlennK.Manacher在1975年提出,首先注意到回文串的对称中心特性可能有所不同(中心可能为一个字符或者是在两个字符之间),那么我们将字母之间插入隔板,这两个回文串的对称中心就都在一个字符上了,suchas"|A|B|B|A|"、"|A|B|C|B|A|"过程对于一个回文串,有且......