Manacher算法

此算法主要是求一个字符串中最长回文字符串的长度。

此算法中会设置一个最右边界值R(R是右边界值再加1,即[L,R-1]为回文字符串),最长回文中心C,每个回文字符串的半径(半径不仅包括中心右边的,也包括中心)

为了能同时处理偶数,奇数回文的情况,在每个字符中插入一个额外字符作为虚轴(任何字符都行,与原字符一样都可),例如:"abcdef" ---> "#a#b#c#d#e#f"。最终结果只需要除2就可以

从左至右依次遍历,每次都会更新上述三个值。

会出现以下两种情况:

1.遍历的点i在最长回文范围外(i>=R),这个时候只能由1开始暴力扩充

2.遍历的点i在最长回文范围内,找到i在此回文范围内以C作为中心的对称点i'(此点一定记录过范围)

1)若i'的范围在最大范围内,则i的范围和i'一样

2)若i'的范围超过了左边界,则i的右边界为R。

3)若i‘的范围正好压在左边界上,那么i的右边界最少到R,需要从R开始继续判断扩充

int Manacher(string s)
{
	string s2 = GetNewString(s);
	int R = -1;//记录最大回文右边界的再右边
	int C = -1;//记录最大回文的中心
	int *Size = new int[s2.size()];//记录每个回文半径(半径包括中心点)
	int max = INT_MIN;
	for (int i = 0; i < s2.size(); i++)
	{
		Size[i] = i < R ? (Size[C - (i - C)] < R - i ? Size[C - (i - C)] : R - i) : 1;//先设置这个点的至少的回文半径
		while (i + Size[i]< s2.size() && i - Size[i] >= 0)
		{
			if (s2[i + Size[i]] == s2[i - Size[i]])
				Size[i]++;
			else
				break;
		}
		if (i + Size[i] > R)
		{
			R = i + Size[i];
			C = i;
		}
		max = max < Size[i]?Size[i] : max;
	}
	return (2*(max-1)+1)/2;
}

string GetNewString(string s)
{
	string res;
	for (int i = 0; i < s.size(); i++)
	{
		res.push_back('#');
		res.push_back(s[i]);
	}
	res.push_back('#');
	return res;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值