馬拉車演算法思想

2021-09-18 06:49:44 字數 1401 閱讀 6583

馬拉車演算法是用來查詢乙個字串的最長回文串的線性方法。正讀與反讀都一樣的字串稱為回文字串。比如 「google」 的最長回文子串為 「goog」。這個演算法的總框架是,遍歷所有的中心點,尋找每個中心點對應的最長回文子串,然後找到所有中心點對應的最長回文子串。

由於回文串的長度可以是奇數也可以是偶數。比如:non,與noon。故馬拉車演算法的第一步是對字串做預處理:在每乙個字元的左右都加上乙個特殊的字元,如  #   則  non ——>#n#o#n#     noon——>#n#o#o#n#   經過了預處理,不論原來的字串是奇數個還是偶數個,現在都是奇數個。

接下來需要乙個 與處理後的字串t等長的陣列p , p[i]記錄 以t[i]為中心的回文串的半徑(不包括p[i]本身)

若p[i]=0表示,該回文子串就是t[i]自身。比如 「#a#b#」 的半徑陣列為 [0, 1, 0, 1  0]。

為了避免在搜尋回文子串時,總是判斷陣列是否越界,我們可以在字串 t 的首尾各加上乙個標誌字元。(注意這兩個字元應在字串 t 中沒有出現過)。如:#n#o#n# ——>  ^#n#o#n# $   陣列 p 的最大半徑,就是我們要尋找的最長回文子串的半徑,只要把 p 陣列求出來,我們便可以找到答案了。

如何計算p 陣列:

馬拉車演算法在計算 p 陣列時,一直在更新兩個變數:

id : 回文子串的中心位置     mx: 回文子串的末端位置

使用這兩個便可以用一次掃瞄來計算出整個p陣列。

公式:p[i] = min( p[2*id - i] , mx - i);

當 mx -  i > p[j]時,以 s[j] 為中心的回文子串  必定包含在  以s[id]為中心的回文子串中, 由於 i 和 j 對稱 ,以 s[i]為中心的回文子串 也一定包含在 以s[id]為中心的回文子串中,所以p[i]=p[j],  由於 j 到id之間的距離 等於  id到 i 的距離。 既  id - j = i - id 移項可得  j = 2*id - i 

當 mx - i <=p[j]時, 以 s[j] 為中心的回文子串不一定完全包含於以 s[id]為中心的回文子串中,據對稱性可知,下圖中兩個綠框所包圍的部分相同,意思就是,以s[i]為中心的回文子串,向右可以擴張到mx位置,即 p[i] = mx - i;  對於mx之後的部分是否對稱,可以用while迴圈去判斷。

馬拉車演算法

思路筆記 上述情況1和情況2又可以歸結為 i 的回文半徑 和 r i的距離 中小的那個就是i的回文半徑。include include includeusing namespace std string manacherstring string str return res int min int...

馬拉車演算法

馬拉車演算法是一種計算最長回文子串的演算法,以其優秀的線性複雜度聞名於世,相較於o n 2 o n 2 o n2 的dpdp dp演算法和會被特殊資料卡到o n 2 o n 2 o n2 的暴力演算法,馬拉車演算法無疑是求解最長回文子串的最優選擇。最長回文子串分為偶數串和奇數串,為了避免這些問題,馬...

馬拉車演算法

manacher char s maxn 1 int n,hw maxn 1 int l maxn 1 r maxn 1 void manacher char a n len 2 2 s n 0 int maxr 0,m 0 for int i 1 i n i manacher 題意在給定的字串中找...