算法-manacher-最长回文子串-1

经典解法:给每个字符前后加入一个特殊(任意字符)字符

manacher算法:

 R 最远回文右边界

 C 最远回文右边界的中心点

 回文直径半径

 回文半径数组

 

 

 

 情况1:

  i没在最远回文边界里 继续暴力扩

 情况2: 

  i在最远回文边界里

    1. i撇的回文区域在最远回文边界里 i的最大回文区域跟i撇的一样

    2. i对应的i撇回文区域已经超出了最远回文边界的左边界 i的最远回文距离半径 是i到最远回文右边界的距离

    3. i撇左边界等于最远回文半径左边界 i从最远右边界位置继续扩 看是否相等

 

 

 1 public class Manacher {
 2     public int maxREStrLength(String s) {
 3         char[] str = addChar(s);
 4         int[] pArr = new int[str.length];
 5         int C = -1; // 中心
 6         int R = -1; // 最右回文边界+1位置
 7         int max = Integer.MIN_VALUE;
 8         for (int i = 0; i != str.length; i++) {
 9             // 1. i撇的回文区域在最远回文边界里 i的最大回文区域跟i撇的一样
10             // L[-,(-,~i,-),-,-,(-,i,-),-]R
11             // 2. i对应的i撇回文区域已经超出了最远回文边界的左边界 i的最远回文距离半径 是i到最远回文右边界的距离
12             // (-,L[-,-,~i,-,-,-),(-,i,-,-])R
13             // 3. i撇左边界等于最远回文半径左边界 i从最远右边界位置继续扩 看是否相等
14             // L[(-,-,~i,-,-),-,(-,i,-,-])R,?
        2*C-i 是i撇  
           15 pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1; 16 while (i + pArr[i] < str.length && i - pArr[i] > -1) { 17 // i到右边界的距离+1 是否等于i到左边界距离-1 18 if (str[i + pArr[i]] == str[i - pArr[i]]) { 19 // 如果相等回文距离+1 20 pArr[i]++; 21 } else { 22 break; 23 } 24 } 25 // i回文边界增加了R 更新C更新 26 if (i + pArr[i] > R) { 27 R = i + pArr[i]; 28 C = i; 29 } 30 max = Math.max(max, pArr[i]); 31 } 32 // #a#a#c#a#a# 33 // max是最大回文半径 c#a#a# 34 // 最大回文直径等于半径-1 = 6-1 = 5 35 return max - 1; 36 } 37 38 private char[] addChar(String s) { 39 char[] chars = s.toCharArray(); 40 char[] newChars = new char[chars.length * 2 + 1]; 41 int index = 0; 42 for (int i = 0; i < newChars.length; i++) { 43 // 1,3,5,7,9 & 1 不等于0 44 newChars[i] = (i & 1) == 0 ? '#' : chars[index++]; 45 } 46 return newChars; 47 } 48 }

 

posted @ 2021-07-26 11:40  rudynan  阅读(51)  评论(0编辑  收藏  举报