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

目錄

Manacher算法解決的問題字符串str中, 最長迴文子串的長度如何求解?如何做到時間複雜度O(N)完成?  

1. 大體理解:

2. 思路剖析

3. 時間複雜度

4. 詳細代碼


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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章