Longest Palindromic Substring最长回文子串-Manacher算法

Manacher算法主要就是用来寻找字符串中的回文子串。

假设目标字符串是abbaca, 在空隙插值#得到新字符串s#a#b#b#a#c#a#
假设当前找到的一个回文串,中心坐标是c, 半径是range(包含自己), 最右边界坐标是r=c+range-1,
那么在s[c-range+1...c)s(c...c+range-1] (s(c...r])中的点对称的。

设p[i]表示以i为中心的最长回文半径,比如p[c]=range。

当i在s(c...c+range-1] 范围内时,在s[c-range+1...c)中镜像坐标为mirror=c*2-i
此时有两种情况

  1. mirror-p[mirror]+1 > c-range+1,这样说明以mirror为中心的最大回文子串,整个范围都在c之内,根据对称性,以i为中心的最大回文子串也在c范围内,故可以直接p[i]=p[mirror]。
  2. mirror-p[mirror]+1 < c-range+1,此时mirror的左边界超过了c的左边界,当利用c的对称性时,必须舍弃超过左边界的范围,此时p[i]=mirror-c的左边界=c的右边界-i作为初始值,之后再继续计算边界外并更新p[i],直到找到i的边界。
public String longestPalindrome(String s) {
        StringBuilder sb = new StringBuilder(s.length() * 2 + 1);
        int n = s.length() * 2 + 1;
        for (int i = 0; i < s.length(); i++) {
            sb.append('#');
            sb.append(s.charAt(i));
        }

        char[] t = sb.append('#').toString().toCharArray();

        int[] p = new int[n];
        int c = 0;
        int r = 0;
        int maxIndex = 0;
        int maxR = 1;
        for (int i = 0; i < n; i++) {
            int mirror = c * 2 - i;
            if (i < r) {
                p[i] = Math.min(p[mirror], r - i);
            }
            while (i - p[i] >= 0 && i + p[i] < n && t[i - p[i]] == t[i + p[i]]) {
                p[i]++;
            }
            if (p[i] > maxR) {
                maxR = p[i];
                maxIndex = i;
            }

        }

        sb.setLength(0);
        for (int i = maxIndex - p[maxIndex] + 1; i < maxIndex + p[maxIndex] - 1; i++) {
            if (t[i] != '#') {
                sb.append(t[i]);
            }
        }
        return sb.toString();

    }

posted on 2025-11-19 21:31  Lv Jianwei  阅读(0)  评论(0)    收藏  举报