終於把馬拉車演算法搞明白了!趕緊記錄一下,以後忘記了還能再回憶起來。
這個演算法用於查詢乙個字串的最長回文子串
馬拉車演算法依次給陣列p[i]賦值,馬拉車演算法的本質就是在每次給陣列p[i] 賦值時嘗試進行偷懶
例如,當要給p[6]賦值時,前面分別以 p[0],p[1],p[2],p[3],p[4],p[5]為中心的回文子串都已經找出來了,
而且這六個回文子串中的 最長的回文子串 和 最靠近右端的回文子串 也找出來了。
如果這個最靠近右端的回文子串特別長的話(怎麼個長法,這是有條件的,看後文),
在找以p[6]為中心的回文子串時就可以偷懶了!哈哈!
乙個小插曲,講個小故事。要結合我下面的兩個條件1和2哦!
說有乙個洋蔥,裡面的某一層有乙個蟲子。要找到這個蟲子就得一層一層的找。我們知道剝洋蔥是從外面往裡面一層一層的剝,
但是這裡找蟲子恰恰相反,必須從裡面往外面一層一層的找。你明白了嗎?
條件1是說 不好意思,咱倆的洋蔥沒有啥關係,所以你就得老老實實的從最裡面的一層開始往外找了。
條件2是說 咱倆的洋蔥m層以內完全相同,已經知道我的洋蔥n層以內都沒有蟲子,
由此可以確定你的洋蔥min以內都沒有蟲子,
所以你找的時候只需要從min+1層往外找就行了。看看,馬拉車演算法偷懶就在這個地方。
插曲講完了,接著說。
1.如果這個最靠近右端的回文子串的右端點mx在i的左邊,那不好意思,你前面找出來的回文子串再多,
對於我現在要找的這個以i為中心的回文子串來說沒有任何幫助,但是考慮到回文子串再短也至少是乙個字元吧,那就先為你賦值為1。
所以後面的while()迴圈語句就得老老實實的從你字元自身兩邊的兩個字元開始向外層依次判斷是否相同,然後找出這個回文子串
2.如果這個最靠近右端的回文子串的右端點mx在i的右邊,嘻嘻!看來有戲!
你前面千辛萬苦找出來的那個最靠近右端的回文子串對於我現在要找的這個以i為中心的回文子串來說就有幫助。
還需要借助上面的小插曲 !
說 你有乙個洋蔥,我有乙個洋蔥,咱倆的洋蔥都是有10層而且5層及以內完全相同,什麼意思,就是5層及以內,你的洋蔥在第幾層有蟲子,
我的洋蔥在第幾層也有蟲子,就是說5層及以內要有蟲子都有,而且位置一樣,要沒有蟲子都沒有。
2.1 如果你的洋蔥3層及以內沒有蟲子,那我的洋蔥也是3層及以內沒有蟲子,
p[2 * id - i] = 3
mx - i = 5
p[i] 只能取兩者的最小值3 故p[i] = p[2 * id - i]
因為你的洋蔥4層和5層有沒有蟲子不確定,那我的洋蔥4層和5層也不確定,所以後面我要從第4層開始往外層找蟲子。
2.2 如果你的洋蔥7層及以內沒有蟲子,那我的洋蔥5層及以內沒有蟲子,因為你的洋蔥6層和7層和我的不一樣,那我的洋蔥6層和7層更加不確定了,
p[2 * id - i] = 7
mx - i = 5
p[i] 只能取兩者的最小值5 故p[i] = mx - i
但是咱倆5層及以內是相同的, 所以後面我要從第6層開始往外層找蟲子。
#include #include #include #include using namespace std;
string manacher(string s)
// process t
vectorp(t.size(), 0);
int id = 0;//記錄最靠近右端的回文子串的中心點
int mx = 0;//記錄最靠近右端的回文子串的右端點
int rescenter = 0;//記錄所有回文子串中最長回文子串的中心點
int reslen = 0;//記錄所有回文子串中最長回文子串的長度
for (int i = 1; i < t.size(); ++i)
//id 和 mx 記錄的是最靠近右端的回文子串的中心點和右端點,但是這個回文子串不一定是最長的回文子串
//所以用 rescenter 和 reslen 記錄目前得到的最長的回文子串
//遍歷到最後記錄的就是要求的最長的回文子串
if (reslen < p[i])
}//根據處理後的最長回文子串的中心點和長度找到這個最長回文子串在原來字串中的位置,然後輸出
return s.substr((rescenter - reslen) / 2, reslen - 1);
}int main()
Manacher 馬拉車演算法
給定乙個字串,求出其的最長回文子串 乙個將時間複雜度優化到o n 的演算法 暴力演算法,但不是純暴力,即按照做過的事情不再去做來優化 我們知道,乙個回文串要麼是奇數的串 aba 要麼是偶數的串 abba 可以看出,乙個回文串有乙個對稱軸 對於奇數串aba來說,對稱軸就是b 而對於偶數串abba來說,...
Manacher演算法(馬拉車)
演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法 kmp和拓展kmp,這次來還是來總結乙個字串演算法,manacher演算法,我習慣叫他 馬拉車 演算法。相對於前面介紹的兩個演算法,manacher演算法的應用範圍要狹窄得多,但是它的思想和拓展kmp演算法有很多共通支出,所以在這裡...
馬拉車演算法manacher
1.預處理解決奇回文和偶回文問題 比如 str bcbaa 在每個字元的開頭,結尾和中間插入乙個特殊字元 來得到乙個新的字串 b c b a a 這樣對於原來字串中的奇回文 bcb 來說,在新的字串中變成了 b c b 還是奇回文,只是回文串長度從3變成了7 注意 中 i 1 0,與1按位與,如果i...