[算法] - Manacher算法【 O(N) 最长回文子串的长度】

目录

Manacher算法解决的问题字符串str中, 最长回文子串的长度如何求解?如何做到时间复杂度O(N)完成?  

1. 大体理解:

2. 思路剖析

3. 时间复杂度

4. 详细代码


Manacher算法解决的问题字符串str中, 最长回文子串的长度如何求解?
如何做到时间复杂度O(N)完成?  

 

1. 大体理解:

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第1张图片

9是指回文子串多的长度

常用的方法:字符串的问题,在两两中间加特殊字符。   然后/2

 

2. 思路剖析

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第2张图片

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第3张图片

 

3. 时间复杂度

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第4张图片

估计while的次数,每个分支必中一个,R变大的意思,就是遍历依次往下走,所以最坏情况是N

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第5张图片

4. 详细代码

public class Code02_Manacher {

	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);// 121 ——> #1#2#1#
		int[] pArr = new int[charArr.length];//r[i] 半径数组
		int C = -1; // 取得R的时候的中心
		int R = -1;// c..R-1是回文半径长度, R-1是代表回文右边界,R是边界的下一个位置
		int max = Integer.MIN_VALUE;// 最大回文半径

		for (int i = 0; i != charArr.length; i++) {
			//R > i表示i在R内,R <= i 表示i在R外,至少的回文半径是1
			//2 * C - i就是i' r[i']与R - i作比较,判别是②的哪个小情况
			// 返回四种情况下i处至少的回文半径是多少
			// 因为有些部分是不需要验证就知道相不相等,所以设置这个
            // 不担心数组越界,因为其实R > i已经有了判断
			pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1;
			while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
				if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
					pArr[i]++;//
				else {
					break;
				}
			}
			if (i + pArr[i] > R) {//表示越界R,需要重新更新
				R = i + pArr[i];//更新R c
				C = i;
			}
			max = Math.max(max, pArr[i]);
		}
		//max是有#的回文半径,需要返回最长的回文子串,直接-1就是,
		//如果要返回没有#的会问半径,直接/2,floor就可以
		return max - 1;
	}
}

[算法] - Manacher算法【 O(N) 最长回文子串的长度】_第6张图片

你可能感兴趣的:(算法,数据结构,编程感悟,CV面经+算法总结)