目錄
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;
}
}