部分內容**:
因為剛開始學,所以有些可能講解的不是特別好。
manacher演算法(民間稱馬拉車演算法233)是用來找字元
串中的最長回文子串的,先來說一下什麼是回文串,像這樣「abcba」這樣乙個字串找到乙個中間位置,然後分別向他的左邊和右邊相等的距離位置的字元是相同的,那麼這個字串就稱為回文串,「abcba」這個字串的len為5是奇數,我們可以找到乙個中間字元,然後進行搜尋也可以找出來(當然時間複雜度是比較高的),但是當我們遇到乙個長度為偶數的字串時該怎麼找中間字元呢,像這樣「abccba」,下面我們引入manacher演算法,這是乙個可以將長度為奇數或偶數的字串一起考慮的神奇演算法
manacher演算法可以將長度為奇數和偶數的回文串一起考慮:在原字串的相鄰字串之間插入乙個分隔符,字串的首尾也要分別新增,注意分隔符必須是原字串中沒有出現過的
原字串sab
abc轉換後字串str#a
#b#a
#b#c
#一、len陣列的簡單介紹
manacher演算法中用到乙個非常重要的輔助陣列len[i]表示以str[i]為中心的最長回文子串的最右端到str[i]位置的長度,比如以str[i]為中心的最長回文串是str[l,r],那麼len[i]=r-i+1
轉換後的字串str#a
#b#a
#b#c
#len12
1414
1212
1len[i]陣列有乙個性質,len[i]-1就等於該回文串在原串s中的長度
證明:在轉換後的字串str中,所有的回文串的長度都是奇數,那麼對於以str[i]為中心的最長回文串的長度為2*len[i]-1,其中又有len[i]個分隔符,所以在原字串中的長度就是len[i]-1,那麼剩下的工作就是求len陣列
二、len陣列的計算
從左往右開始計算,假設0<=j<=i,那麼在計算len[i]時,len[j]已經計算過了,設mx為之前計算過的最長回文串的右端點,id為取得這個端點值得位置(那麼len[id]=mx-id+1)
第一種情況:i<=mx.
找到i相對於id的對稱位置,設為j,再次分為兩種情況:
mx的對稱點為2*id-mx,i和j所包含的範圍是2*len[j]-1
那麼說明以j為中心的回文串一定在以id為中心的回文串內部,且i和j關於id對稱,由回文串的定義可知,乙個回文串反過來仍是回文串,所以以i為中心的回文串長度至少和以i為中心的回文串長度相等,即len[i]>=len[j].因為len[j]
由對稱性說明以i為中心的回文串可能延伸到mx之外,而大於mx的部分我們還沒有進行匹配,所以要從mx+1位置開始乙個乙個匹配直到失配,從而更新mx和對應的id以及len[i]
第二種情況,i>mx
如果i比mx還大,說明對於中點為i的回文串一點都沒匹配,這個時候只能乙個個匹配(滑稽),匹配完成後更新mx的位置和對應的id及len[i].
下面推薦一道模板題:luogu p3805 【模板】manacher
#includeusingnamespace
std;
const
int n = 11000001
;char s[n*2],str[n*2
];int len[n*2
],lenn;
void
getstr()
void
manacher()
}int
main()
Manacher學習筆記
目錄manacher演算法 可在 o n 的時間內求出乙個字串以每個位置為中心的最長回文子串。原理 根據之前預處理出的回文串長度求得新的回文串長度 我們可以通過在字元中加上 來避免長度為偶數回文串沒有中心的問題 原串 abcd 變為 新串 a b c d 原串中長度為奇數和偶數的回文串的長度均變為奇...
學習筆記 Manacher演算法
manacher 中文 馬拉車 演算法,即求解給定字串中最長回文子串長度的演算法。洛谷p3805 給出乙個長度為 n 的只由小寫英文本元 mathtt 組成的字串 s 求 s 中最長回文串的長度 一般情況下回文串有奇偶分類。為了避免分類,我們在字串中間新增特殊字元 不妨用 在串的首尾加上不同的特殊字...
學習筆記 manacher演算法
一.關於manacher manacher演算法用於求解乙個字串的回文子串半徑長度。它可以線性地求解對於字串中的每乙個字元,以它本身為中心的最長回文串的半徑。而且這個回文串的每乙個以這個字元為中心的子串都是回文串。這個演算法的時間複雜度為o n 二.回文子串長度的奇偶性帶來的問題。當乙個回文串長度是...