manacher算法详解

manacher算法用于 

字符串预处理:aba 处理成 #a#b#a#,方便处理偶回文和奇回文,代码如下

string manacherString(string original_str){
	string res(original_str.size() * 2 + 1, ' ');
	int index = 0;
	for (int i = 0; i < res.size(); i++) {	
		res[i] = (i & 1) == 0 ? '#': original_str[index++];//(i & 1) == 0代表i是偶数
	}
	return res;
}

 


概念

回文半径:#a#b#a#字符串一共七个字符, 回文半径分别为1, 2,1, 4,1, 2, 1

回文半径数组:#a#b#a#的回文半径数组就是[1, 2,1, 4,1, 2, 1],回文半径数组的最大值减一就是最长回文子串长度,无论是回文半径最大值发生在实轴还是虚轴上。

回文右边界:#a#b#a#字符串中,以第一个字符a为回文中心的回文右边界就是字符b


回文数组的求取:设待求取位置为i, 右边界为R,回文中心为 C , i关于回文中心C对称的位置为i'

讨论分为两大情况,4种小情况

一.i不在右边界里,暴力向两边扩展,无法优化

二.i在右边界里

1.i'的回文半径在边界里, i处半径与i'处半径相同

2.i'的回文半径超过了边界,i处从边界处开始扩展

3.i'的回文边界与边界重合,i处也是冲边界处开始扩展

情况如下图:

初始值:右边界和回文中心都为-1

int maxPalindromeString(string str) {
	if (str.size() == 0) {
		return 0;
	}
	str = manacherString(str);
	cout << str << endl;
	vector<int> pArr(str.size());
	int center = -1;
	int right = -1;
	int maxLen = INT_MIN;
	for (int i = 0; i < str.size(); i++)
	{
		pArr[i] = right > i ? min(pArr[2 * center - i], right - i) : 1;//几种情况都扩展处理
		while (i + pArr[i] < str.size() && i - pArr[i] > -1) {
			if (str[i + pArr[i]] == str[i - pArr[i]]){
				pArr[i]++;
			}
			else {
				break;
			}
		}
		if (i + pArr[i] > right)
		{
			right = i + pArr[i];
			center = i;
		}
		maxLen = max(maxLen, pArr[i]);
	}
	return maxLen - 1;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值