Manacher's Algorithm 马拉车算法

题目:Longest Palindromic Substring

题目简述

找出最长回文子串,如输入"babad",结果为"bab"或"aba"。

马拉车算法

引入

可以观察到回文串根据中心对称,反之可以从中心向两边扩张去寻找最大回文串。一共有2n+1个中心,每个都尝试一下便可以得出答案。为了操作方便,添加分隔符#。
如:babaabac——> #b#a#b#a#a#b#a#c


image.png

T为加分割符后的字符串,L[i]代表以T[i]为中心的最长回文子串的长度。最后找出最大的L为13,(13-1)/2后为原字符串的最长回文子串的长度。

上述算法时间复杂度为O(n2),在具体求解每个L[i]时都需要O(n)的时间复杂度,有没有办法可以提高效率呢?

若从左向右遍历求解,回文串的特性可以发挥一定作用。设L[0]-L[8]已求出,且已经得知T[8]为中心,左边界为T[2],右边界为T[14]是回文串。那么接下来L[9]=L[7]=3,L[10]=L[6]=1,.....,但注意L[3]!=L[13]。具体分析看下文。

根据回文特性简化

若前面已经求出了以C为中心,R为右边界的某个回文串,现在正要求的以i为中心的最大回文串长度。若i<=R,则可以根据对称规则求解,若i>R则只能蛮力求解。

设P为回文半径,即表示以字符T[i]为中心的最长回文字串的最端右字符到T[i]的长度。注:P[i]-1 即为原回文子串的长度

四种情况

  1. i>R
    T[i-1]与T[i+1]匹配...T[i-2]与T[i+2]匹配...直至超出字符串边界,或T[i-k]!=T[i+k]

  2. i<=R且i+(P[i']-1)<R
    P[i] = P[i']

  3. i<=R且i+(P[i']-1)>R
    P[i] = R-i+1
    例:如下图,由于T[15]!=T[11]回文串被截断


    截断.jpg

    有没有可能T[15]==T[11]呢?
    若T[15]=T[11](已知T[11]=T[5]=T[1]),则T[1]=T[15],P[8]=7+1与P[8]=7矛盾,所以T[15]不可能等于T[11]。因此一定会被截断。

  4. i<=R且i+(P[i']-1)=R
    P[i]>=R-i+1
    首先,P[i]至少可以是R-i+1,后面可能会有其他的字符使得回文子串继续加长,但也可能没有。具体有没有需要再一一匹配,但匹配的基础是R-i+1。T[i-(R-i+1)]与T[(i+(R-i+1)]匹配..T[i-(R-i+2)]与T[(i+(R-i+2)]匹配...

Python代码

class Solution:
    def longestPalindrome(self, s: str) -> str:
        c = 0
        r = -1
        T = '#' + '#'.join(s) + '#'
        P = [1]*(len(T))
        max_index = 0
        for i in range(len(T)):
            if i<= r:
                P[i] = min(r-i+1,P[2*c-i])
            # Try to extend
            while i-P[i]>=0 and i+P[i]<len(T) and T[i+P[i]]==T[i-P[i]]:
                P[i] += 1
            # 循环中顺便找出最长回文子串的中心
            if P[i]>P[max_index]: 
                max_index = i
            if i+P[i]-1 >r:
                c = i
                r = i+P[i]-1
        #根据映射关系返回原子串
        return(s[(max_index-P[max_index]+2)//2:(max_index+P[max_index]-2)//2+1])
if __name__ == "__main__":
    l = 'babad'
    t = Solution()
    r = t.longestPalindrome(l)
    print(r)

总结

  1. 通过加分割符的方法,使每个中心位置都可以取到,也使字符串长度统一为奇数
  2. 马拉车算法主要运用的是回文串的特性

Reference:

  1. https://www.hackerrank.com/topics/manachers-algorithm

  2. http://javabin.cn/2018/manacher.html

  3. https://www.cnblogs.com/love-yh/p/7072161.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容