manacher求最大回文长度


manacher能求出最大回文长度,并且时间复杂度为o(logn)。

实现该算法主要步骤:

1.构造p[ i ]值,记录每个字符回文数。

2.由于平时求回文得考虑奇偶情况,所以在字符间插入符号#(或其他没出现在字符串里的),这样就能将两种情况都转化成奇数的情况。(经典)


          # a # b # a # b # a # b # c # a # b # d

P[i]:   1 2 1 3 1 6 1 6 1 4 1 2 1 2 1 2 1 2 1 1

    观察知,当i=4时,p[ i ] = 3.问题:此时p[ i ] = 3是如何根据前面的p[ i ] 所推导得出的呢?


综合上述情况得出核心代码:

if(MaxId>i)   

p[i]=Min(p[2*id-i],MaxId-i);

else

p[i]=1;

hdu3086求最大回文长度

#include <stdio.h>
char b[100020],a[200040];
int p[200040];
int Min(int a,int b)
{
	 return a<b?a:b;
}
int main()
{
	int i,n,id,MaxL,MaxId;
	while(scanf("%s",&b[1])!=EOF)    //输入时从b[1]地址开始存储字符串
	{
	
		for(i=1;b[i]!='\0';i++)
		{
			a[(i<<1)]=b[i];
			a[(i<<1)+1]='#';
		}
				//  预处理
		MaxL=MaxId=0;
		a[0]='?';a[1]='#';   
		n=(i<<1)+2;a[n]=0;   //防止溢出
		MaxId=MaxL=0;      //maxid记录对称最大回文后一位值,maxl记录最大回文数
	
		for(i=1;i<n;i++)
		{
			if(MaxId>i)    //核心重点!!!! 画图更清晰
			{
				p[i]=Min(p[2*id-i],MaxId-i);
			}
			else
			{
				p[i]=1;
			}
			while(a[i+p[i]]==a[i-p[i]])  //判断i的前后是否一致,p[i]为前后距离i的长度
			{
				p[i]++;
			}
			if(p[i]+i>MaxId)   //更新maxid的值,必须取最大区间
			{
				MaxId=p[i]+i;
				id=i;        //id记录最大回文的轴的i值
			}
			if(p[i]>MaxL)
			{
				MaxL=p[i];  //maxl记录左边最大回文长度
			}
		}   
		printf("%d\n",MaxL-1);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值