Manacher算法讲解与Java实现

  • Manacher算法原理
    该算法原型就是求解字符串中的最长回文子串,字符串的长度可能是技术或者偶数,所以首先要对字符串进行填充,例如“abc”变为“#a#b#c#”。

  • 算法中的三个要素
    1)回文半径数组(以当前字符为中心所形成回文字符串的半径大小所组成的数组)
    2)最右回文右边界(以当前字符为中心所形成回文字符串的最右边的字符的位置)
    3)回文右边界的中心

  • 如何求解回文半径数组
    如果对每个字符都暴力的去扩充求回文半径,那么就不能实现O(n)的时间复杂度,所以求回文半径数组的时候需要分情况来讨论。
    1)当前字符不再回文右边界内,直接暴力扩求其半径;
    2)当前字符在回文右边界内部,再分三种情况:
    1.假设当前最右回文右边界的回文中心是C,那么当前字符i关于C的对称字符 i‘ 的回文半径是已知的,当 i‘ 的回文字符串的左边界小于C的左边界,那么i的回文半径就等于 i’的回文半径。
    2.假设当前最右回文右边界的回文中心是C,那么当前字符i关于C的对称字符 i‘ 的回文半径是已知的,当 i‘ 的回文字符串的左边界小于C的左边界,那么i的回文半径就等于i到C的右边界。
    3.假设当前最右回文右边界的回文中心是C,那么当前字符i关于C的对称字符 i‘ 的回文半径是已知的,当 i‘ 的回文字符串的左边界等于C的左边界,那么i的回文半径就等于C的右边界继续往外扩,直到不再以i为中心形成回文,同时更新最右回文右边界。

  • 代码实现

public static char[] manacherString(String str){
	char [] charArr = str.toCharArray();
	char [] res = new char [str.length*2+1];
	int index = 0;
	for(int i=0; i!=res.length; i++){
		res[i] = (i & 1) == 0? '#' : charArr[index++];
	} 
	return res;
}
public static int maxLcpsLength(String str){
	if(str==null || str.length()==0){
		return 0;
	}
	char [] charArr = manacherString(str);
	int [] pArr = new int [charArr.length];
	int index = -1;//回文中心
	int pR = -1;//回文右边界
	int max = Integer_MIN_VALUE;
	for(int i=0; i != charrArr.length; i++){
		pArr[i] = i<pR? Math.min(pArr[2*index-i], pR-i) : 1;
		while(i + pArr[i] < charArr.length&&i - pArr[i]){
			if(charArr[i+pArr[i]] == charArr[i-pArr[i]]){
				pArr[i]++;
			}else{
				break;
			}
		}
		//更新回文右边界以及回文中心;
		if(i + pArr[i] > pR){
			pR = i + pArr;
			index = i;
		}
		max = Math.max(max , pArr[i]); 
	}
	return max - 1;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值