题目描述:
    image.png
    输入输出Demo:
    image.png
    解析:在LeetCode上本题属于Medium难度。用Manacher算法求解。
    需要先明白几个概念:1.回文半径数组 2.最右回文右边界 3.取得最右边界时,中心在哪里
    回文直径:以一个中心点 i ,往左右扩,其长度为回文直径,例 __i_,那么,扩一半的长度,就为回文半径,例 i_,存入辅助数组(即回文半径数组)
    最右回文右边界:例012131210
    初始R当前停在-1索引的位置:
    image.png
    当要扩0的时候,发现没扩的,R停在索引为0的位置:
    image.png
    继续扩1,发现没扩的,R停留在索引为1的位置:
    image.png
    继续扩2,此时R到了索引为3的位置:
    image.png
    继续扩1,发现没扩的,R保持原来的索引位置:
    image.png
    继续扩3,此时R到了末尾:
    image.png
    ……C继续往右扩,R就是最右回文右边界,C为其中心点

    1. class Solution {
    2. public String longestPalindrome(String s) {
    3. //首先预处理,将原字符串转变为例如“#a#b#c#”的形式
    4. StringBuilder stringBuilder = new StringBuilder("#");
    5. for (int i = 0; i < s.length(); i++) {
    6. stringBuilder.append(s.charAt(i)).append("#");
    7. }
    8. s = stringBuilder.toString();
    9. int[] RL = new int[s.length()]; //回文半径数组(保存的是当前字符的回文半径)
    10. int c = -1, maxRight = -1; //c为中心点,maxRight为最大回文右边界,初始化为-1
    11. for (int i = 0; i < s.length(); i++) { //遍历所有的s,求当前i所指向字符的回文半径
    12. /**
    13. * 有两种可能性
    14. * 1.若当前字符在最大回文右边界外面(直接暴力往外扩)
    15. * 2.若当前字符在最大回文右边界里面:(此时有3种可能)
    16. * 2.1 i'回文在L,R内
    17. * 2.2 i'回文在L,R外
    18. * -----> RL[i]=min(RL[i'],R-i)
    19. * 2.3 i'回文的左边界与L压线
    20. */
    21. if (i >= maxRight) { //说明i在回文右边界外面(直接暴力往外扩)
    22. RL[i] = 1; //i自己算做一个长度,由此向外扩
    23. } else { //说明i在回文右边界里面 (2.1和2.2情况)
    24. RL[i] = Math.min(RL[2 * c - i], maxRight - i);
    25. }
    26. //尝试以i位置往外扩,注意处理边界(全部都往外扩,避免分情况讨论)
    27. while (i - RL[i] >= 0 && i + RL[i] < s.length()) { // 0<=回文左边界左边一位<=回文右边界右边一位<=s.length()
    28. if (s.charAt(i - RL[i]) == s.charAt(i + RL[i])) { //左边界和右边界的下一个点
    29. RL[i] += 1;
    30. } else {
    31. break; //没匹配上的直接跳出
    32. }
    33. }
    34. if (i + RL[i] > maxRight) {
    35. maxRight = i + RL[i]; //更新最右边界和中心点
    36. c = i;
    37. }
    38. }
    39. int maxLen = 0;
    40. int centerIndex = 0;
    41. for (int idx = 0; idx < RL.length; idx++) {
    42. if (RL[idx] > maxLen) {
    43. maxLen = RL[idx];
    44. centerIndex = idx;
    45. }
    46. }
    47. return s.substring(centerIndex-maxLen+1,centerIndex+maxLen).replace("#","");
    48. }
    49. }