参考知乎一位作者的写法,有时间再改成c++.
链接:https://www.zhihu.com/question/330983016/answer/726069573
问题:
马拉车用来搜索最长回文子串。
普通的搜索方法为逐一的向两端扩展,时间复杂度是O(n*n)。
马拉车算法的时间复杂度是线性的为O(n)。
1 链接:https://www.zhihu.com/question/330983016/answer/726069573 2 3 public String preProcess(String s) { 4 int n = s.length(); 5 if (n == 0) { 6 return "^$"; 7 } 8 String ret = "^"; 9 for (int i = 0; i < n; i++) 10 ret += "#" + s.charAt(i); 11 ret += "#$"; 12 return ret; 13 } 14 15 // 马拉车算法 16 public String longestPalindrome2(String s) { 17 String T = preProcess(s); 18 int n = T.length(); 19 int[] P = new int[n]; 20 int C = 0, R = 0; 21 for (int i = 1; i < n - 1; i++) { 22 int i_mirror = 2 * C - i; 23 if (R > i) { 24 P[i] = Math.min(R - i, P[i_mirror]);// 防止超出 R 25 } else { 26 P[i] = 0;// 等于 R 的情况 27 } 28 29 // 碰到之前讲的三种情况时候,需要利用中心扩展法 30 while (T.charAt(i + 1 + P[i]) == T.charAt(i - 1 - P[i])) { 31 P[i]++; 32 } 33 34 // 判断是否需要更新 R 35 if (i + P[i] > R) { 36 C = i; 37 R = i + P[i]; 38 } 39 40 } 41 42 // 找出 P 的最大值 43 int maxLen = 0; 44 int centerIndex = 0; 45 for (int i = 1; i < n - 1; i++) { 46 if (P[i] > maxLen) { 47 maxLen = P[i]; 48 centerIndex = i; 49 } 50 } 51 int start = (centerIndex - maxLen) / 2; //最开始讲的求原字符串下标 52 return s.substring(start, start + maxLen); 53 }