首页 > 其他分享 >马拉车 Manacher

马拉车 Manacher

时间:2025-01-22 16:53:22浏览次数:1  
标签:typedef string int Manacher long 拉车 回文 define

更新日志 2025/01/22:开工。

思路

马拉车算法用于解决回文子串问题,思路类似于Z函数

首先我们考虑使所有回文串都是奇数串,具体的,我们在两两字符之间插入相同的特殊字符,比如:

\[\texttt{abcba}\rightarrow\texttt{\#a\#b\#c\#b\#a\#} \]

不难发现此时所有回文串串长均为奇数。

类似地,我们考虑 \(p_i\) 表示 \(i\) 为中心最长回文串的半长,储存最大的 \(i+p_i-1\)(我令 \(p_i\) 包含中心字符),将这段半长的左右端点记作 \(l,r\)。

image

首先,一个位置 \(i\) 的对应位置为 \(j=2l-i\),简单推式子。

若 \(p_j\) 不超过整个红框的左边界,由于整个红框都是回文串,那么 \(p_i=p_j\)。

否则,我们暴力向外扩展即可。

细节

更改字符串,如果使用加法,请使用 += 而不是 = +,因为后者复杂度是 \(O(|A|+|B|)\) 的。

模板

(当前字符串为中心的最长回文串长度为 \(p_i-1\))

int p[N],l,r;
void manacher(string t){
	string s="#";
	repl(i,0,t.size())s+=t[i],s+='#';
	p[0]=1;l=r=0;int len=s.size();
	repl(i,1,len){
		if(i<=r&&p[l-(i-l)]<r-i+1)p[i]=p[l-(i-l)];
		else p[i]=max(1,r-i+1);
		while(i+p[i]<len&&i-p[i]>=0&&s[i+p[i]]==s[i-p[i]])p[i]++;
		if(i+p[i]-1>r)r=i+p[i]-1,l=i;
	}
}

例题

LG3805

代码
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
typedef double db;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
template <typename Type>
using vec=vector<Type>;
template <typename Type>
using grheap=priority_queue<Type>;
template <typename Type>
using lrheap=priority_queue<Type,vector<Type>,greater<Type> >;
#define fir first
#define sec second
#define pub push_back
#define pob pop_back
#define puf push_front
#define pof pop_front
#define chmax(a,b) a=max(a,b)
#define chmin(a,b) a=min(a,b)
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repl(i,x,y) for(int i=(x);i<(y);i++)
#define per(i,x,y) for(int i=(x);i>=(y);i--)

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=998244353;

const int N=2.2e7+5;

string s;
int ans=1;

int p[N],l,r;
void manacher(string t){
	string s="#";
	repl(i,0,t.size())s+=t[i],s+='#';
	p[0]=1;l=r=0;int len=s.size();
	repl(i,1,len){
		if(i<=r&&p[l-(i-l)]<r-i+1)p[i]=p[l-(i-l)];
		else p[i]=max(1,r-i+1);
		while(i+p[i]<len&&i-p[i]>=0&&s[i+p[i]]==s[i-p[i]])p[i]++;
		if(i+p[i]-1>r)r=i+p[i]-1,l=i;
		chmax(ans,p[i]-1);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>s;
	manacher(s);
	cout<<ans;
	return 0;
}

标签:typedef,string,int,Manacher,long,拉车,回文,define
From: https://www.cnblogs.com/HarlemBlog/p/18686407

相关文章

  • Manacher 学习笔记
    \(\text{Manacher学习笔记}\)一、引入首先我们需要知道的是\(\text{Manacher}\)是解决回文串问题的有效工具。一个通用的问题模型是给定一个长度为\(n\)的字符串\(s\),统计该字符串中所有的回文子串的个数。\(\text{Manacher}\)算法可以在\(O(n)\)的时间复杂度内解决这......
  • Luogu P4287 SHOI2011 双倍回文 题解 [ 紫 ] [ manacher ]
    双倍回文:回文子串结论的经典应用。结论先放本题最关键的结论:一个字符串本质不同的回文子串最多只有\(n\)个。考虑如何证明:假设我们一个一个地在当前字符串(黑色部分)的结尾加入字符(红色部分),那么会出现如下情况:显然,加入红色字符后,字符串中最多只可能新出现一个本质不同的回文......
  • Luogu P9646 SNCPC2019 Paper-cutting 题解 [ 紫 ] [ manacher ] [ 贪心 ] [ 哈希 ] [
    Paper-cutting:思维很好,但代码很构式的manacher题。蒟蒻2025年切的第一道题,是个紫,并且基本独立想出的,特此纪念。判断能否折叠我们先考虑一部分能折叠需要满足什么条件。显然,这一部分需要是一个长度为偶数的回文串。那么横向和纵向会不会影响呢?答案是不会,因为横向折了之后,折......
  • Manacher
    Manacher,O(n)求字符串最长回文子串的良心算法首先,求最长回文字串的两个个方法,第一个是将所有字串列出来然后逐个判断,时间复杂度高达O(n3),这里不多赘述,然后就是选择一个字符,向两边扩展,判断是否相等,相等则长度自增。时间复杂度高达O(n2)然后就是可以用hash来判断回文,时间复杂度为O......
  • 【知识】Manacher
    Manacher#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;constintN=2e7+10;intn;chara[N],b[N];intp[N];voidinit(){intk=0;b[k++]='$',b[k++]='#';......
  • [学习笔记 #8] Manacher 算法
    目录[学习笔记#8]Manacher算法[学习笔记#8]Manacher算法至今都不会exKMP/dk/dk/dk[]里的是我还不确定的。Manacher是对序列上每个点求它作为[回文中心]的最长回文子串长度/端点的算法,时间复杂度是\(O(|S|)\)。具体地,从左往右加入每个点,记录当前字符串的回......
  • 马拉车算法(C/C++)
    #1024程序员节|征文#马拉车算法(Manacher'sAlgorithm)是一种用于在字符串中查找最长回文子串的线性时间复杂度算法。该算法由UdiManacher在1980年代提出,因此得名。它的核心思想是利用已知的回文信息来减少不必要的比较,从而提高效率。算法步骤预处理字符串:为了处理奇数......
  • Manacher 马拉车
    Manacher马拉车,一种为了求字符串中最长的回文字串的算法。这个算法是从暴力的方法转化过来的,暴力肯定是枚举字符串每个字符作为中心,然后向外扩展,这样的复杂度为\(O(n^2)\)。而Manacher则是按照回文对称的性质的进行优化的,首先回文串有奇数串\(aba\)和偶数串\(abba\)如果......
  • Manacher 算法
    引入:万恶的字符串问题你是否看到字符串就感到迷茫而无所适从?你是否看到“border”“回文”等字眼就感到大脑宕机只会暴力?如果你像我一样有这种症状,不妨一起来学习一下Manacher算法。当你掌握了Manacher之后,你会发现,很多字符串问题都变成了板子,而你再也不用担心因为字符串抱......
  • 算法·理论:Manacher 笔记
    \(\text{Manacher}\)来啦!\(\text{Manacher}\)并没有什么前置知识,比\(\text{KMP}\)简单多了。前置处理\(\text{Manacher}\)算法用于解决回文串相关问题,先看几个基本概念:回文中心、回文半径,这些看字面意思就能猜到。还有一个重要问题:对于回文串,有长度为奇数或长度为偶数之......