Manacher 学习

先来一段代码压压惊:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1e5+5;

char str[maxn],str2[maxn*2];
int Len[maxn];

int string_init() {
	str2[0] = '$';
	str2[1] = '#';
	int len = 2;
	int length = strlen(str+1);
	for (int i = 1;i<=length;i++) {
		str2[len++] = str[i];
		str2[len++] = '#';
	}
	str2[len-1] = '$';
	str2[len] = '\0';
	return len;
}

int Manacher() {
	int len = string_init();
	int mxlen = -1,maxr = -1,middle = -1;
	for (int i = 1;i < len;i++) {
		if ( maxr < i ) {
			int j = 1,cnt = 1;
			while ( str2[i-j] == str2[i+j] ) j++,cnt += 2;
			Len[i] = cnt; middle = i; maxr = i + j;
			mxlen = max(mxlen,Len[i]);
		} else if ( maxr > i && Len[2*middle-i] == (maxr-i) ) {
			int j = maxr - i,cnt = Len[2*middle-i];
			while ( str2[i-j] == str2[i+j] ) j++,cnt+=2;
			Len[i] = cnt; middle = i; maxr = i + j;
			mxlen = max(mxlen,Len[i]);
		} else if ( maxr >= i ) {
			Len[i] = min(Len[2*middle-i],maxr-i);
		}
	}
	return mxlen;
}

int main() {
	while(~scanf("%s",str+1)){
		printf("%d\n",(Manacher()+1)/2);
	}
	return 0;
}

想像一下对于一个字符串,如何求它的最长的回文子串,暴力的做法就是枚举每一个点然后往两边扩,但是这个算法的时间复杂度是 O ( n 2 ) O(n^2) O(n2)时间很不进人意,于是就诞生了Manacher算法

Manacher

开始Manacher之前我们首先要准备两个变量maxr和middle ,maxr 和 middle 依次表示 回文串的最大右边界,和 最大右边界的回文串的中心

(1).

如果maxr小于当前要查找的回文中心,我们就暴力寻找(这一点可以参见,我的Manacher函数中的第一个if)

if ( maxr < i ) {
		int j = 1,cnt = 1;
		while ( str2[i-j] == str2[i+j] ) j++,cnt += 2;
		Len[i] = cnt; middle = i; maxr = i + j;
		mxlen = max(mxlen,Len[i]);
}
(2).

这里写图片描述
请看图片如果当前要寻找的位置 i i i,在maxr里面我们可以在回文的对称一边找到 i ′ i&#x27; i 并且如果 i ′ i&#x27; i的回文串左边界比maxl大的话,那么我当前位置 i i i的回文子串的长度就跟 i ′ i&#x27; i的一样

else if ( maxr >= i ) { // 为什么是min(Len[2*middle-i],maxr-i);呢往下看
	Len[i] = min(Len[2*middle-i],maxr-i);
}
(3).

这里写图片描述
在第二种的基础上,我的 i ′ i&#x27; i的回文串的左边界比maxl要小,但是此时 i i i的回文串的长度为 m a x r − i maxr - i maxri 可以证明一下为什么不等于 i ′ i&#x27; i的回文串长度,如果我当前位置的回文子串长度等于 i ′ i&#x27; i的话,那么在maxl和maxr两端的外部是不是还有一段连续相等的串,既然这样的话我的middle得回文串的长度应该更大,可是事实没有更大,因此当前位置的回文子串的长度为 m a x r − i maxr - i maxri
######(4).
最后一种情况 : 当我的 i i i位置的对称点回文左边界刚好与maxl重合
因为不知道当前位置外面的串的情况,因此对于这种情况暴力寻找回文串

###时间复杂度估计
因为我的maxr不断向右走并且没有重复走的情况等于说我只遍历了一遍串因此时间复杂度为 O ( n ) O(n) O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值