算法随笔——manacher

非常好学习资料

manacher

求最长回文子串

暴力

枚举回文中心 [1,n],暴力向两边拓展,然后 checkmax。时间复杂度 O(n2)
可以用二分哈希优化至 O(nlogn)

算法思路

当求解第 i 个字符为回文中心的时候,已经知道了 [1,i1] 之间的信息。
于是引入
p[i] :以 i 为中心的最长回文半径(即回文串的一半)
r :回文串右端点最远可以到达的位置,则该设回文串为 [l,r]
m[l,r] 回文串的中心,m=(l+r)/2,始终满足 m<i
k :i 关于 m 的对称点,k=2mi
image
image

因此 p[i]=min(ri+1,p[2mi])

小tips

因为回文串有奇有偶,因此为了避免讨论,在每个字符之前和首尾插入一个 '#',可以保证每个回文串长度均是奇数,答案即为 maxp[i]1

char old[N],str[N];

int p[N],r,m;

int main()
{
	scanf("%s",old+1);
	int len = 0;
	//插入字符 初始化
	str[++len] = '#';
	for (int i = 1,l = strlen(old+1);i <= l;i++)
		str[++len] = old[i],str[++len] = '#';
	for (int i = 1;i <= len;i++)
	{
		if (i > r) p[i] = 1;
		else p[i] = min(p[2*m-i],r-i+1);
		while (i+p[i] <= len && i - p[i] >= 1 && 
		str[i+p[i]] == str[i-p[i]]) p[i]++; //暴力拓展
		//更新中心和最远右端点
		if (i + p[i] - 1 > r) r = i + p[i] - 1,m = i;
	}
	int ans = 0;
	for (int i = 1;i <= len;i++ ) ans = max(p[i],ans);
	cout << ans - 1 << endl;
	//答案等于(整条回文串-1)/2
	//即(p[i]*2-1 -1)/2 = p[i]-1
	return 0;
}
posted @   codwarm  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示