Manacher算法

2019-06-12  本文已影响0人  topshi

前言

Manacher算法用于求解字符串中最长的回文子串,它和KMP算法的改进方式很类似,都是基于暴力求解的方法,通过利用历史信息进行优化。所谓回文子串是指以子串中间字符为中心,左右两端是对称的。例如,cbcacb的最长回文子串为bcacb,其长度为5。
相关题目:5. 最长回文子串

最长回文子串的暴力求解

Manacher算法

Manacher算法基于暴力求解做出优化,它定义了如下几个概念:

我们的“扩”是基于一个中心向外扩的,扩出来的回文子串长度必是奇数。为了处理回文子串为偶数的情况,我们在字符间插入一个字符#以保证回文子串长度都是奇数。例如,字符串cbcacb - > #c#b#c#a#c#b#

Manacher算法如何利用pArrCR对查找进行加速

我们以指针cur去遍历字符串,

综上所述,分四种情况:

时间复杂度

相关题目

最长回文子串

class Solution {
    public String longestPalindrome(String s) {
        if(s.length() < 2) return s;
        char[] m = manacherString(s);
        int[] pArr = new int[m.length];
        int c = -1;
        int r = -1;
        int maxLen = -1;
        StringBuilder maxStr = new StringBuilder();
        for(int i = 0;i != m.length;i++){
            //i在r右边,直接1;否则就是pArr[cur']或R - cur + 1
            pArr[i] = i < r ? Math.min(pArr[2 * c - i], r - i + 1) : 1;
            //看能不能扩(针对压中L和暴力扩的情况)
            while(i - pArr[i] >= 0 && i + pArr[i] < m.length
                  && m[i - pArr[i]] == m[i + pArr[i]]){
                pArr[i]++;
            }
            if(i + pArr[i]- 1 > r){
                c = i;
                r = i + pArr[i] - 1;
            }
            if(maxLen <= pArr[i]){
                maxLen = pArr[i];
                maxStr.delete(0,maxStr.length());
                for(int j = i - pArr[i]+1;j < r;j++){
                    if(m[j] != '#'){
                        maxStr.append(m[j]);
                    }
                }
            }
        }
        return maxStr.toString();
    }
    private char[] manacherString(String s){
        char[] m = new char[2 * s.length() + 1];
        for(int i = 0;i < m.length;i++){
            m[i] = i % 2 == 0? '#' : s.charAt(i / 2);
        }
        return m;
    }
}
上一篇下一篇

猜你喜欢

热点阅读