O(n)时间求字符串的最长回文子串

感谢https://www.felix021.com/blog/read.php?2040
HDOJ3068
#include<iostream>
#include<cstring>
#include<algorithm> 
const int MAX=110005;
char s1[MAX];
char s[2*MAX+2];//增加MAX+1个‘#’和一个‘$’ 
int d[2*MAX+2];
using namespace std;
int main()
{
	while(cin>>s1)
	{
		memset(d,0,sizeof(d));
		memset(s,0,sizeof(s));
		
		//字符串预处理 
	   int ans=1;
	   int len=strlen(s1);
	   s[0]='&';
	   for(int i=1;i<=2*len+1;i+=2)
	   {
	   	s[i]='#';
	   }
	   int k=0;
	   for(int i=2;i<=2*len;i+=2)
	   {
	   	s[i]=s1[k++];
	   }
	   
	   //debug
	   /*for(int i=0;i<strlen(s);i++)
	   {
	   	cout<<s[i]<<" ";
	   }
	   cout<<endl;*/
	   
	   
	   
	   int id=0,mx=0;
	   d[0]=1;d[1]=1;d[2]=2;
	   //mx是以id为中心的回文字串的右边缘(不在字串内) 
	   //id是已知的回文字串中,右边缘最靠右的子串的中心
	   id=2;mx=id+d[id];
	   
	   for(int i=3;s[i]!='\0';i++)
	   {
	   	
	   	//j是i关于id的对称点
	   	int j=2*id-i;
	   	
	   	//当i<mx,d[i]>=min(mx-i,d[j]) 
	   	if(i<mx)
	   	{
			if(d[j]<mx-i)
			{
				d[i]=d[j];
			}  
		  
			else
			{
				d[i]=mx-i;
			}
		}
		
		//当i>=mx的时候,的d[i]=1; 
		else d[i]=1;
		
		/*
		上13行可写成d[i]=i<mx?min(d[2*id-i],mx-i):1; 
		*/ 
		
		//确定了d[i]的最小值之后,超出部分逐个比较 
		while(s[i+d[i]]==s[i-d[i]])
			d[i]++;
		
		//更新id,mx的值 
		if(i+d[i]>mx)
		{
			mx=i+d[i];
			id=i;
		}
	   
        //更新最大值 
		if(d[i]-1>ans)
		ans=d[i]-1;
	   } 
	   
	   //输出答案 
	   cout<<ans<<endl;
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值