最長回文子串 manacher演算法

2021-07-16 06:52:18 字數 1471 閱讀 2923

像kmp一樣,先來看一道題目

給出乙個長度為n的字串s,

求s的子串t,令t反轉後t`與t完全相等,求t最大的長度。

首先,可以想到用暴力做,列舉所有的子串,然後判斷,時間複雜度為o(

n3)

第二,可以發現,如果子串s[1..5]是乙個回文串,那麼s[2..4]自然也是乙個回文串。

利用這個性質,可以列舉所有串的回文中心,然後從中間向兩邊去查詢、判斷。

最後的時間複雜度為o(

n2)

顯然,這仍然不夠優,kmp能夠實現線性時間完成,那麼這個問題也能用線性的時間完成嗎?

答案是肯定了,這就需要manacher這個演算法來實現。

首先,可以充分利用剛才發現的規律,就可以通過左半部分的對稱中心的答案得到右半邊的對稱中心的答案

如果是乙個回文串s

s:caaabaaaaabaaac

那麼,可以得到乙個陣列

ans

分別是1131713f31

? 這個f就是十六進製制下的15

可以發現,f所在的位置就是s串的中心,

首先,以此可以發現s[

1..15]=

s[1..15]′

然後根據s[

5]的數字發現s[

2..8]=

s[2..8]′

再根據上一句,可以得到s[

2..8]=

s[8..14]

那麼s[11

] 至少為7

最後比較發現s[

7]≠s

[15]

所以s[11

] 的答案小於9,最後得到7

所以manacher演算法的原理就是從左到右求各個中心的答案,然後根據最長的回文串再來根據左邊的回文中心的答案推出右邊的答案。

如果需要s[

i]的答案,就查詢s[

2p−i

] 用這種方法可以避免重複比較,也充分地利用了前面的資訊

但是現在仍然有乙個問題,如果長度是偶數的怎麼解決。

答案是在字串前加上乙個未出現過的字元,然後在原有的字元之間再插入這個字元,最後再加上乙個,但是防止越界,於是在開頭再放乙個另一種字元,在結尾也放乙個沒有出現過的字元。

這樣做,就可以把所有偶數的情況都轉化為奇數。

以下為**:

int manacher()  else 

while(t[i - len[i]] == t[i + len[i]])

if(len[i] + i > mx)

ans = max(ans, len[i]);

}return ans - 1;

}

那麼,最後再來看一下時間複雜度,不難猜到,這也是利用線性時間就能解決問題的演算法,這個演算法在執行時,while每執行一次,p至少向右移一下,所以while最多執行n次,其他的跟著for迴圈最多執行n次,所以最終總時間為o(

n)

O n 時間求 最長回文子串 Manacher演算法

回文字串分為奇回文和偶回文,在字串中間插入任意字元使得串變成奇回文串 暴力思想 肯定是找乙個點往兩邊任意擴充套件,遍歷一次,manacher時間為o n 開乙個陣列p記錄 以點i為中點 的最長回文串的半徑,假設前i 1個點的p都已經求出來來,現在考慮p i 如何推導 重點 r是p 1 p i 1 中...

Manacher 最長回文子串

最長回文子串問題 給定乙個字串,求它的最長回文子串長度。如果乙個字串正著讀和反著讀是一樣的,那它就是回文串。下面是一些回文串的例項 12321 a aba abba aaaa tattarrattat 牛津英語詞典中最長的回文單詞 對於最長回文子串問題,最簡單粗暴的辦法是 找到字串的所有子串,遍歷每...

Manacher 最長回文子串

caioj任意門 hz2016評測傳送門 可以的話來一下hz2016評測吧,有的題caioj沒有的我也可以給到資料嘛。include include include include include include include include define maxchar 100000 defin...