目录
Manacher算法解决的问题字符串str中, 最长回文子串的长度如何求解?如何做到时间复杂度O(N)完成?
Manacher算法解决的问题字符串str中, 最长回文子串的长度如何求解?
如何做到时间复杂度O(N)完成?
1. 大体理解:
9是指回文子串多的长度
常用的方法:字符串的问题,在两两中间加特殊字符。 然后/2
2. 思路剖析
3. 时间复杂度
估计while的次数,每个分支必中一个,R变大的意思,就是遍历依次往下走,所以最坏情况是N
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;
}
}