专题·马拉车(manacher)【including 洛谷·【模板】manacher算法

初见安~:)

manacher

众所周知,马拉车算法是用来教马怎么拉车求最长回文字符串的一个均摊复杂度O(n)的算法

其原理也十分有趣,就是充分运用了之前处理出来的信息。

我们用数组maxlen[i]表示从i这个点往左右延伸的最大长度。就比如字符串abcba,【从1开始】,maxlen[3]=5。那如果是长度为偶数的回文串呢?我们的处理方式就是:在每个字符中间插入一个非字母字符【比如‘#】用以区分,然后照样跑即可。显然匹配时一定会在一个'#'匹配后停下,所以我们要保证字符串头尾也都是'#"。这样一来,我们要找的就全都是奇回文串了。

为了方便,我们让maxlen[i]的含义变为往右延伸的最大长度(包括i自己)。比如上面的例子,maxlen[3]=3。在插入了'#'字符后maxlen[3]=6,刚好是答案+1。

接下来我们看怎么跑。

假设前面有一个点mid作为中点,匹配回文串可以最远匹配到mx。

现在我们在点i的位置,关于mid对称有一个点j。

因为mid的对称性,我们首先可以判断i处的答案至少为min(maxlen(j),mx-i)。取min是因为j的匹配可能超出了mid-maxlen(mid),而这一部分并不和mx后面的部分相同。

但其实i可能还可以继续匹配。所以我们这时候可以暴力继续往后匹配。

还有一种情况是,i并不在mx以内。这时候我们没法利用前面的信息,初始化maxlen[i]=1,同样暴力往后匹配。

因为我们一直在更新mx,也就是说暴力匹配的话一定可以更新mx的大小,这样一来就最多匹配n次,复杂度\mathcal{O}(n)

模板题:洛谷P3805 【模板】manacher算法

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxl 11000010
using namespace std;
typedef long long ll;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

char s[maxl << 1];
int max_len[maxl << 1], len = 0;
signed main() {	
	char ch = getchar(); s[0] = '#';
	while(isalpha(ch)) s[++len] = ch, s[++len] = '#', ch = getchar();
	
	int ans = -1, mx = 0, mid = 0;
	for(int i = 1; i <= len; i++) {
		if(i < mx) max_len[i] = min(max_len[(mid << 1) - i], mx - i);//分情况
		else max_len[i] = 1;
		while(s[i - max_len[i]] == s[i + max_len[i]] && i + max_len[i] <= len && i >= max_len[i]) max_len[i]++;
		if(max_len[i] + i > mx) mx = max_len[i] + i, mid = i;//更新mx
		ans = max(ans, max_len[i] - 1);//注意答案要-1
	}
	printf("%d\n", ans);
	return 0;
}

迎评:)
——End——

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值