hdu 3068最长回文 Manacher算法

点击打开链接

参考

Manacher 通过记录已匹配的最右位置和对应的对称中心 利用和对称性来跳过一些没用的比较

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio> 
using namespace std;
const int M =111000;
char s[M];
char t[2*M]; //转换后字符串长度为奇数 
int p[2*M];// p[i] 以i为中心点的回文的右端长度 
int len;
void Init()
{
	int i;
	len=strlen(s);
	t[0]='@';//防止越界 
	for(int i=1;i<=2*len;i+=2)
	{
		t[i]='#';
		t[i+1]=s[i/2];
	 }
	 t[2*len+1]='#';//最后一个
	 t[2*len+2]='$';//防止越界
	 t[2*len+3]=0;//结束标记
	 
	len=2*len+1;//转换后 字符串长度 
}
void MANACHER()
{
	int mx=0,ans=0,po=0;// i之前最大p为po po最右端点为mx 
	for(int i=1;i<=len;i++)
	{
		if(mx>i)
		{
			
			p[i]=min(p[2*po-i],mx-i); // i关于po对称点为 (i+j)/2=po  j=2*po-i	
			
			//情况1 j-len[j]~~i+len[j]如果在po范围内-> lem[i]>=len[j] (画个图推一个咯)
			
			//情况2 如果i+len[j]>mx 现在只能确定i-(mx-i)~~i+(mx-i)为回文  因为mx之后的没匹配过不能确定  (画个图推一个咯)
			
		
		
		}
		else
		{
			p[i]=1;//mx之后的位置还没有被匹配过 所以此时开始推 
			
		}
		while(t[i-p[i]]==t[i+p[i]]) 
		p[i]++;
		if(p[i]+i>mx)//update
		{
			mx=p[i]+i;
			po=i;
		}
		ans=max(ans,p[i]);
	}
	ans-=1;// 新串回文长度为 2*p[i]-1  '#'的个数比原串字符多1 (画图推) x+(x-1)==2*p[i]-1 x=p[i] 所以其它字符即原串的回文长度为p[i]-1 
	printf("%d\n",ans);
} 
int main()
{
	while(scanf("%s",s)!=EOF)
	{
		
		Init();	
		MANACHER(); 
		
		

	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值