Manacher 马拉车板子

本文详细介绍了Manacher算法,一种在O(n)时间内找出字符串中最长回文串的高效算法。通过预处理和中心扩展策略,理解p[i]的计算过程,以及如何利用已知回文串长度来逐步更新最长回文串。

Manacher算法是一种通过O(n)的时间复杂的算出字符串最长回文串的一种算法
在这里插入图片描述
因为回文串可能是奇数也可能是偶数,不好判断,为了保证字符串回文串总是一个奇数,先对字符串进行预处理,每隔一个字符,插入一个特殊的字符,保证其总是一个奇数
用p[i]表示字符串中以i为中心的最长回文串半径
对于奇数回文串
在这里插入图片描述
偶数回文串同理
可以发现max(p[i]-1)就是我们要的最大回文串长度

那么如何计算p[i]呢?
令mx为上一次操作的最长回文子串的最右端的下一位,mid为mx对应回文串的中心点。
如果i大于等于mx,先让p[i]=1,然后以i为中心开始遍历其最长的回文串,并对p[i]做出改变,操作完成后,更新新的mx和mid
如果i小于mx,说明该字符已经包含在某字符串里,根据回文串的对称关系
p[i]=p[2*mid-i],但由于以2*mid-i为中心的回文串可能会大于原回文串长度
所以p[i]=min(mx-i,p[2*mid-i])
这样可以从mx开始继续统计新的回文串长度,从而实现mx新的更新

int manacher()
{
	int sum=0,k=1;
	//构建新的奇数总串 
	s[k++]='#';
	for(int i=0;i<a.size();i++)
	{
		s[k++]='#';
		s[k++]=a[i];
	}
	s[k]='#';
	//开始计算最长长度
	int mx=0,mid;
	for(int i=1;i<=k;i++)
	{
		if(i<mx)
		p[i]=min(mx-i,p[2*mid-i]);
		else
		p[i]=1;
		while(s[i-p[i]]==s[i+p[i]])
		p[i]++;
		if(i+p[i]>mx)
		{
			mx=i+p[i];mid=i;sum=max(sum,p[i]);
		}
	}
	return sum-1;
}
### 马拉算法介绍 马拉算法,也称为 Manacher 算法,是一种用于解决最长回文子串问题的高效算法。该算法能够在 $O(n)$ 的时间复杂度内找出给定字符串中的最长回文子串,其中 $n$ 是字符串的长度。由于其线性的时间复杂度,在处理较长字符串时,马拉算法相较于暴力算法具有明显的效率优势 [^2]。 ### 马拉算法原理 马拉算法的核心思想是利用已知的回文子串信息,尽可能地减少重复计算。该算法定义了两个关键变量:当前回文中心位置 `center` 和最右边的回文边界 `right`。算法会依次遍历整个字符串,检查当前位置是否包含在回文半径之内。若包含,则可以利用已知的回文信息,直接计算出该位置的回文半径,从而减少计算时间;若不包含,则需要暴力地扩展回文中心并计算新的回文半径。在计算过程中,记录下每个位置的最长回文半径,即可得到最长回文子串 [^1]。 ### 马拉算法应用 - **文本处理**:在文本编辑和处理中,需要快速找到最长的回文段落,以进行特殊标记、校对或其他操作。 - **生物信息学**:在 DNA 序列分析中,寻找最长的回文子序列有助于发现特定的基因结构或模式。 - **数据加密**:回文结构可用于某些加密算法中,马拉算法可以帮助快速找到合适的回文密钥。 ### 马拉算法实现 以下是使用 Python 实现的马拉算法示例代码: ```python def manacher(s): # 预处理字符串,插入特殊字符 t = '#'.join('^{}$'.format(s)) n = len(t) p = [0] * n center = right = 0 for i in range(1, n - 1): if right > i: # 利用已知回文信息 p[i] = min(right - i, p[2 * center - i]) # 尝试扩展回文中心 while t[i + (1 + p[i])] == t[i - (1 + p[i])]: p[i] += 1 # 更新回文中心和最右边界 if i + p[i] > right: center, right = i, i + p[i] # 找到最大回文半径及其中心位置 max_len, center_index = max((n, i) for i, n in enumerate(p)) start = (center_index - max_len) // 2 return s[start: start + max_len] # 测试示例 s = "babad" print(manacher(s)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值