回文子串(模板)Manacher O n 演算法

2021-07-11 00:15:33 字數 2614 閱讀 4214

回文子串和回文子串行不同:

子串,一定要連續

子串行,不一定連續

其實最長回文子串是可以轉換成lcs來做的,具體方法就是:

將原串生成反向串,然後用dp求原串和反向串的lcs

但是這樣缺點也很明顯的是o(n*n)的複雜度,即使優化到:滾動陣列+下標找反向串,也不能從根本上解決這個演算法的低效。

如果想在 o(n) 時間內解決回文子串問題呢?

答案就是manacher演算法,用一句話來概括這個演算法:

通過記錄已匹配的最右位置對應的對稱中心來跳過一些沒用的比較

在下面的**中,這個已匹配的最右位置就是mx,對稱中心就是id。

完整模板

int manacher(string tmp) 

s[2*k] = '#';

s[2*k+1] = '\0';

//演算法核心

len=strlen(s);

int mx =0; //mx 記在i之前的回文串中,延伸至最右端的位置

int id=0; //id 記下取得這個最優mx時的 座標值

for (int i=0;i

}int res =0;

for (int i=0;i

return res-1;

}

演算法在字串開頭、結尾、字元之間都插入特殊字元(這裡用』#』),這樣就巧妙的把奇數的回文串和偶數的回文串統一起來考慮了(統一為奇數),不然處理回文串會很麻煩。

比如:abc 變成 #a#b#c# 這樣有7個字元。

abcd 變成 #a#b#c#d# 有9個字元。

可能有疑問:預處理成這樣,後面不是要算回文子串長度的時候,又要減去這些特殊字元嗎。

其實不會,因為演算法用 p[i] 來記錄 i 這個 pos 的最長單臂子串長度,比如 #a#b#c#b#a# 這個單臂子串長度為 #a#b#c,即長度為6,

而這裡有乙個很好的性質,p[i]-1 就是該回文子串在原串中的長度。即 abcba 就是5

其實manacher演算法的核心**很簡單,但是理解起來感覺相當精妙,果然是演算法是**寫成的詩歌

核心**:

//演算法核心

len=strlen(s);

int mx = 0; //mx 記在i之前的回文串中,延伸至最右端的位置

intid=0; //id 記下取得這個最優mx時的 座標值

for (int i=0;iif( i < mx ) //在當前最優邊界左邊

p[i] = min(p[2*id-i],mx-i); //算出對稱初始值

else

p[i]=1; //如果超出mx邊界,p[i]初始值為1

for (;s[i-p[i]] == s[i+p[i]] && s[i-p[i]] != '\0' && s[i+p[i]] != '\0' ; ) //對於超出mx或者p[j]邊界的計算

p[i]++;

if( p[i]+i > mx )

}

演算法開始是會通過乙個if else判斷來決定p[i]的初始值。

演算法的關鍵點就在這裡:

if( i < mx ) //在當前最優邊界左邊

p[i]= min(p[2*id-i],mx-i); //算出對稱初始值

else

p[i]=1; //如果超出mx邊界,p[i]初始值為1

那為什麼是 min(p[2*id-i],mx-i) 呢?

這種情況下,整個 中心i(或中心j) 的子串都涵蓋在 中心為 id,長度為 mx-id 的巨型臂膀下,由於 id為中心的完全對稱,必然 p[j] == p[i],

這種情況下,是 id 的臂展無法完全包裹 以i為中心的臂展時:

根據對稱性可知,圖中兩個綠框所包圍的部分是相同的,也就是說以 i 為中心的回文子串,其向右至少會擴張到mx的位置,也就是說 p[i] >= mx - i。至於mx之後的部分是否對稱,就只能乙個乙個匹配了。

另外特別要注意的是,要注意設定「哨兵」,也就是自己設定特殊字元或者』\0』代表邊界,不然後面的

for (;s[i-p[i]] == s[i+p[i]] ; p[i]++);
就會越界。

給出我畫出的原手稿

下圖中,當i為13時,臂展最大,但是這個字元的p[i]初始化為6,即 i = 5那個點 『c』。

[1]

[2]

最長回文子串模板

這裡先提前注意一下,子串和子串行是兩個不同的東西 回文串是面試常常遇到的問題 雖然問題本身沒啥意義 本文就告訴你回文串問題的核心思想是什麼。首先,明確一下什 回文串就是正著讀和反著讀都一樣的字串。比如說字串aba和abba都是回文串,因為它們對稱,反過來還是和本身一樣。反之,字串abac就不是回文串...

近似回文串 最長回文子串

輸入一行文字,輸出最長近似回文詞連續子串。所謂近似回文詞是指滿足以下條件的字串 1.s以字母開頭,字母結尾 2.a s 和b s 最多有2k個位置不同,其中a s 是s刪除所有非字母字元並且把所有字母轉化成小寫之後得到的串,b s 是a s 的逆序串。比如當k 1時,race cat是乙個近似回文詞...

回文子串對 擴充套件kmp kmp與回文子串

problem 1 回文子串對 manacher.cpp c pas 題目描述 給定一長度為n的小寫字母串,求有多少對回文子串,它們的交集非空。一對回文子串的交集非空 a,b c,d a c或b d 為2個回文子串,且 a,b c,d 輸入格式 第一行乙個整數n表示串長。第二行長度為n的小寫字母串。...