Manacher(马拉车)算法

Manacher(马拉车)

简介

一种字符串算法,能够在 \(O(n)\) 复杂度解决如下问题:

给定一个长度为 \(n\) 的字符串 \(s\),找到字符串中最大的回文子串。

使用哈希复杂度是 \(O(n\log n)\)

实现

考虑处理出一个数组 \(d1_i\)\(d2_i\) 代表以位置 \(i\) 为中心的长度为奇数和长度为偶数的回文串个数。二者也表示了以位置 \(i\) 为中心的最长回文串的半径长度。

例如:

  • \(abcbac\),以第一个 \(c\) 为中心,可以找出回文串 c,bcb,abcba 共三个,\(d1_i=3\),所以回文串长度为 \(3\times 2-1=5\)

  • \(abba\),以第一个 \(b\) 为中心,可以找出回文串 bb,abba 共两个,\(d2_i=2\),所以回文串长度为 \(2\times 2=4\)

偶数和奇数的处理方式是不同的。但如果我们将字符串中任意两个字符间都放一个 # 字符的话,原字符串的偶数长度回文串就变为了 # 字符的奇数长度回文串。

答案为 \(\max d_i-1\),减去的是 # 的贡献。

考虑如何实现。

先维护已经找到的最靠右的子回文串的两个端点 \((l,r)\)。初始时 \(l=0,r=-1\)

考虑现在要计算一个 \(d_i\)\(d_1\sim d_{i-1}\) 的值都已经被计算。

  • \(i>r\) 即当前 \(i\) 处于回文串之外,考虑朴素算法。

连续的增加 \(d_i\),每次判断 \(i-d_i\) 是否和 \(i+d_i\) 一样。注意更新 \((l,r)\)

  • \(i\le r\),即当前 \(i\) 处于回文串之中,考虑利用已经处理的算法计算答案。

考虑 \(i\)\((l,r)\) 的对称位置 \(i'\)

由于 \((l,r)\) 是回文串,所以 \(i'\) 的回文串可以复制到 \(i\) 上,即 \(d_{i'}\to d_i\)

注意 \(i'\) 的回文串右端点可能会 \(>r\),此时是不一定合法的(因为 \(r\) 之后的字符不一定满足对称性),所以 \(d_i\) 初始值最大为 \(r-i\)

由于 \(d_i\) 还有可能更大,所以考虑用朴素算法继续拓展。

复杂度分析

每次执行朴素算法都会让 \(r\) 增加,复制 \(i'\) 的贡献不会产生时间复杂度,所以 \(O(n)\)

Code

scanf("%s",s+1);
t[++n]='!';
t[++n]='#';
int len=strlen(s+1);
F(i,1,len)
{
	t[++n]=s[i];
	t[++n]='#';
}
t[++n]='#';
int l=0,r=-1,ans=1;
F(i,1,n)
{
	if(i<=r)
	{
		int ii=l+(r-i);
		d[i]=MIN(d[ii],r-i+1);
	}
	else d[i]=1;
	while(t[i+d[i]]==t[i-d[i]]) d[i]++;
	if(i+d[i]-1>r) r=i+d[i]-1,l=i-d[i]+1;
	ans=MAX(ans,d[i]-1);
}

「POI2010」Antisymmetry

分析

发现一个字符串需要满足 \(s_{i+k}\oplus s_{i-k}=1\) 就是不相同,做马拉车的时候判断反过来就行。

容易发现的是奇数长度的一定不满足。

思路

处理 \(d\) 数组,最后答案怎么计算?

比如 #1#0#\(d_i=3\),贡献了一个子串 10

比如 #1#1#0#0#\(d_i=5\),贡献了两个子串 101100

注意题目问的是子串所以可以重复,不用去重。所以答案为 \(\sum \frac{d_i}{2}\)

细节

  • ## 可以匹配。

具体来讲可以使用一个 map 记录,mp[#]=#,mp[1]=0,mp[0]=1

  • 只处理 t[i]=# 的情况。因为答案只和偶长度回文串有关,处理了其他 t[i] 的话会导致 \((l,r)\) 被乱改。

Code

int l=0,r=-1;
F(i,2,n-1)
{
	if(t[i]!='#') continue;
	if(i<=r)
	{
		int ii=l+(r-i);
		d[i]=MIN(d[ii],r-i+1);
	}
	else d[i]=1;
	while(t[i+d[i]]==mp[t[i-d[i]]]) d[i]++;
	if(i+d[i]-1>r) r=i+d[i]-1,l=i-d[i]+1;
}
int ans=0;
F(i,2,n-1) if(t[i]=='#') ans+=d[i]/2;
put(ans);
posted @ 2024-12-05 17:21  _E_M_T  阅读(46)  评论(0)    收藏  举报