Manacher算法

Manacher算法的应用

求出字符串的最长回文子串。

Manacher算法的流程

1、插入特殊字符

因为回文串的长度可能是奇数或偶数,为了不考虑这么多情况,就插入一些特殊字符。
比如:abcddcba
插入后变成:#a#b#c#d#d#c#b#a#
所以可以将问题转化成求长度为奇数的回文串。

2、求出每一位为中心的最长回文子串

p i p_i pi为以i为中心的最长回文子串。
如何求 p i p_i pi
通过前面的信息,首先要求出Maxright和pos。
Maxright为前面所求的回文字符串中最靠右的右端点,pos为Maxright所对应的中心点。
分两种情况讨论:

  1. i在Maxright的左边。先找到i关于pos的对应点j( j = 2 ∗ p o s − i j=2*pos-i j=2posi)。如果将j的回文串复制到i,保证的回文长度为 min ⁡ ( p [ j ] , M a x r i g h t − i ) \min (p[j],Maxright-i) min(p[j],Maxrighti),在这个基础上尽量往两边扩展。
  2. 否则,保证的回文长度为1,在这个基础上往两边扩展。
    然后更新Maxright和pos。

3、统计答案

例题

Palindrome

using namespace std;
#include <iostream>
#include <cstring>
#include <algorithm>
char str[1000003];
char s[2000007];
int p[2000007];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int T=1;
	for (cin>>str;str[0]!='E';++T,cin>>str)
	{
		int len=1;
		s[0]='#';
		for (char* ch=str;*ch;++ch)
		{
			s[len++]=*ch;
			s[len++]='#';
		}
		p[0]=1;
		int pos=0,Maxright=0,ans=0;
		for (int i=1;i<len;++i)
		{
			if (i<Maxright)
				p[i]=min(p[(pos<<1)-i],Maxright-i);
			else
				p[i]=1;
			int j,k;
			for (j=i-p[i],k=i+p[i];j>=0 && k<len && s[j]==s[k];--j,++k);
			p[i]=k-i;
			if (k-1>Maxright)
			{
				Maxright=k-1;
				pos=i;
			}
			ans=max(ans,p[i]-1);
		}
		cout<<"Case "<<T<<": "<<ans<<'\n';
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值