hihocoder 1032 最长回文子串

本文介绍了两种求解最长回文子串的方法:一种是枚举中心点的O(n^2)方法,适用于n较小的情况;另一种是Manacher算法,时间复杂度为O(n),适用于大数据量场景。通过插入特殊字符将所有回文串转换为奇数长度,并使用数组p记录以各字符为中心的最长回文半径。

一般的求最长回文子串,我喜欢用两种方法。

当n不是很大时,我们可以用O(n^2)的方法, 即枚举中心点,然后向两边进行比较,当然长度为偶数的回文串是没有中心点的,所以我们得按照奇数和偶数两种进行求解。


char s[N];
void findLongestPalindrome(char *s){	//以枚举回文串的中心点来寻找回文串,时间复杂度(On^2),要分长度为奇偶两种情况
	int len = strlen(s);
	int maxlen = 0;
	int st;
	for(int i=0;i<len;i++){		//回文串长度为奇数的时候
		int j = i-1;k=i+1;
		while(j>=0&&k<len&&s[j]==s[k]){
			if(k-j+1>maxlen){
				maxlen = k-j+1;
				st = j;
			}
			j--;
			k++;
		}
	}
	for(int i=0;i<len;i++){		//回文串为偶数的时候
		int j = i;k = i+1;
		while(j>=0 && k<len && s[j] == s[k]){
			if(k-j+1>maxlen){
				maxlen = k-j+1;
				st = j;
			}
			j--;
			k++;
		}
	}
//	for(int i=st;i<st+maxlen;i++){
//		printf("%c",s[i]);
//	}
	printf("%d\n",maxlen);
}
但是对于这道题目来说,n有10^6,所以n^2效率肯定是不行的,这个数量级的基本也就是用O(n)效率算法来解决了。

这种算法被称为manacher算法。

manacher算法能达到O(n)的原因是因为它定义了一个数组p[i],代表以第i个字符为中心,最长回文子串的半径为p[i],神奇的是,后面的p[i]可以利用前面已经算出的p[i]进行推导。

先给出Mancher算法的核心代码:

void findLongestPalindrome(char *s){	//
	int len = strlen(s);
	int id=0,maxlen=0;
	k=0;
	ch[k++] = '*';
	for(int i=0;i<len;i++){
		ch[k++] = '#';
		ch[k++] = s[i];
		if(i==len-1)
			ch[k++] = '#';
	}
	ch[k++] = '\0';
//	printf("%s\n",ch);
	memset(p,0,sizeof p);
	for(int i=2;i<2*len+1;i++){
		if(p[id]+id>i)
			p[i] = Min(p[2*id-i],p[id]+id-i);
		else
			p[i] = 1;
		while(ch[i-p[i]] == ch[i+p[i]])
			p[i]++;
		if(p[id]+id<i+p[i])
			id = i;
		if(maxlen<p[i])
			maxlen = p[i];
	}
	printf("%d\n",maxlen-1);
}
刚才说了,算法是基于有个中心点的,所以偶数长度的无法处理,我们的做法是可以再每个字符中心加个没有出现过的符号,如'#',这样,所有的回文串的长度就都是奇数了。

p[id]刚才说了,是以第id个字符为中心的最长回文串的半径,那么如果现在循环到了第i个字符,那么如果在id<i中没有半径覆盖到i(即p[id]+id<=i),那么此时我们已知的最长回文子串的长度为1,剩下的就是向两边扩展比较了。

上面的是第一大情况,对于第二大情况,如果有p[id]+id>i,说明第i个字符之前已经在某个回文串之内了。

这种情况又分为3种情况。


这就是第一种情况,图中的i就是我们说的id,i+kj就是我们说的i,那么因为i+k是在以i为中心回文串种,那么与i+k对应的就是i-k那部分,如果i-k回文串有一部分在i的半径外,那么其实是不可能的,因为如果这样,那么i的半径就随之延伸了。所以此时p[i+k] = p[i]+i-k (对应到代码中就是p[i]=p[id]+id-i)。





这是第二种情况,就是i-k-[i-k]在以i为半径之内,说明我们现在遍历到的i+k最长的回文串长度也是在p[i]半径之内的,所以此时p[i+k] = p[i-k](在代码中就是p[id-(i-id))]=p[2*id-i];




第三种情况的p[i+k]值是和第二种情况是一样的,但是在这种情况下p[i+k]的值还可能增加,因为再往外延伸时,我们就不知道了,而第二种情况下p[i+k]=p[i-k],不可能再增加了。

上面的两大情况和3种小情况合起来就能得出以上的核心代码。



内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性与能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员与工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航与避障;②研究智能优化算法(如CPO)在路径规划中的实际部署与性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构与代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略与约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为与系统鲁棒性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值