第五章_最长回文子串

本文介绍了如何使用Manacher算法解决寻找字符串中最长回文子串的问题,并通过C++代码实现了解法。文章分为两部分:第一部分详细解释了枚举中心位置并使用扩展法的基本解法;第二部分则引入Manacher算法,提供了一种更高效的解决方案,能够统一处理长度为奇数或偶数的情况。通过实例演示了如何将所有情况转换为奇数处理,最终实现了O(N)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给定一个字符串,求它的最长回文子串的长度。


解法一

枚举中心位置,然后再在该位置上用扩展法,记录并更新得到的最长的回文长度

 

#include<iostream>
#include<cstring>
using namespace std;
int longestPalindrome(char *s,int n)
{
	
	if(s==NULL||n<1)
	{
	return 0;
	}else if(n==1)
	{
	return 1;
	}
	char* first=s;
	char* last=s+n-1;
	char* str1;
	char* str2;
	int max=1;
	int len;
	if(n%2!=1)//长度n为偶数:maddam
	{

		while(first<last)
		{
			len=0;
			str1=first;
			str2=first+1;
			while(str1>=s)
			{
				if(*(str1--)==*(str2++))
				{
				len=len+2;
				}
				else
				{
				break;
				}				
			
			}
		max=max>len?max:len;
		first++;
		
		}
	
	}
	else //长度n为奇数:madam
	{
		while(first<last)
		{
			len=1;
			str1=first-1;
			str2=first+1;
			while(str1>=s)
			{
				if(*(str1--)==*(str2++))
				{
				len=len+2;
				}	
				else
				{
				break;
				}				
			}
		max=max>len?max:len;
		first++;		
		}
	
	}
	return max;	
}	
	

int main()
{
char*str1="cdmadamegfh";
char*str2="fsdgmaddamgf";
cout<<longestPalindrome(str1,11)<<endl;//5
cout<<longestPalindrome(str2,12)<<endl;//8

return 0;
}
解法二、O(N)解法

在上文的解法一:枚举中心位置中,我们需要特别考虑字符串的长度是奇数还是偶数,所以导致我们在编写代码实现的时候要把奇数和偶数的情况分开编写,是否有一种方法,可以不用管长度是奇数还是偶数,而统一处理呢?比如是否能把所有的情况全部转换为奇数处理?

答案还是肯定的。这就是下面我们将要看到的Manacher算法:

#include<iostream>
#include<cstring>
using namespace std;
void stringTransform(char cstr1[],char cstr2[])
{
    int ix2=0;
    cstr2[ix2++] ='#';
  for(int ix1=0;cstr1[ix1]!='\0';++ix1)
  {
    cstr2[ix2++]=cstr1[ix1];
	cstr2[ix2++]='#';
  }
  cstr2[ix2]='\0';
}
void longestPalindrome(char cstr2[],int p[])
{
	int right=0;//当i=0时,right=0,center=0,所以下面循环无需再判断i=0时的情况
	int center=0;
	for(int i=1;cstr2[i]!='\0';i++)
	{
		if(right-i>0)
		p[i]=p[2*center-i]>(right-i)?(right-i):p[2*center-i];//p[i]=min{p[2*center-i],(right-i)}

		while(cstr2[i+p[i]+1]!='\0'&&(i-p[i]-1>=0)&&cstr2[i+p[i]+1]==cstr2[i-p[i]-1])
		p[i]++;

		if(i+p[i]>right)
		{
		center=i;
		right=i+p[i];
		}
	}


}


int main()
{
char *cstr1="babcbabcbaccba";
char cstr2[25];
int p[50];
for(int i=0;i<50;i++)
{
p[i]=0;
}

stringTransform(cstr1,cstr2);
cout<<cstr2<<endl;
longestPalindrome(cstr2,p);

for(int j=0;j<strlen(cstr2);j++)
{
cout<<p[j];
}
cout<<endl;

return 0;
}


http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值