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

2021-09-20 10:20:34 字數 1817 閱讀 7201

回文字串分為奇回文和偶回文,在字串中間插入任意字元使得串變成奇回文串

暴力思想:肯定是找乙個點往兩邊任意擴充套件,遍歷一次,

manacher時間為o(n)

開乙個陣列p記錄 以點i為中點 的最長回文串的半徑,

假設前i-1個點的p都已經求出來來,現在考慮p[i]如何推導

重點:rp[1]~p[i-1]中推出來的右端最遠最長回文子串的右端點,且用pos記錄下來,每一步更新pos+r,既然r知道了,l也知道(沒啥意義)

當前遍歷到i點,j是與i對稱的點,且 j=p

os−(

i−po

s)j=pos-(i-pos)

j=pos−

(i−p

os)->j=2

pos−

ij=2pos-i

j=2pos

−i,我們可以通過j點來得到i點的p[i]

此時i j r有三種情況

a. 第乙個圖中紅色都在[l,r]範圍內,r-i>p[j],直接得到p[i]的值,p[i]=p[j]

此時j點的回文子串只有一部分在[l,r](最大的回文子串)中,那麼超出範圍的肯定不符合要求,r-i=r,現在只能往兩邊暴力擴充套件了

先更新p,有三種情況

向兩邊暴力擴充套件回文字串,滿足前兩種情況這一步肯定擴充套件不出來新的回文串,所以不需要特殊判斷是否if(p[i]==1),所以這一步往兩邊擴充套件

更新[l,r]右端最遠的回文子串,並且記錄pos的值,

這是(插入字元的奇數字串)上的一系列操作,我們要轉化成源字串上的位置長度這裡是2個結論,自己對比就可以知道了,

原字串的位置:index = (resid - reslen)/2

源字串的長度:len = reslen-1

#include #include #include using namespace std;

int main()

if ( reslen < p[i] )

}string ans=t.substr( (resid-reslen)/2 , reslen-1 );//求出來的最長回文子串

cout << ans.size() << endl;//長度

}return 0;

}

求最長回文子串

求最長回文子串,大概有以下幾種方法 1 錯誤!先翻轉再求最長公共子串 例如 abcdafdcba abcd x 即原串中包含翻轉串的子串時 2 暴力 遍歷每個字串,然後判斷是否是回文子串並記錄最長資訊 時間複雜度o n 3 3 動態規劃 時間複雜度o n 2 空間複雜度o n 2 dp i j 表示...

求最長回文子串

1.第一種方法 o n 2 動態規劃,用s i j 表示從i到j是最長回文字串,用乙個table i j 記錄字串從i到j是否為回文,這樣的話,從底部向上,table i i true 另外如果s i s i 1 則table i i 1 true,然後長度從3開始,如果s i 1 s j 1 則就...

求最長回文子串

利用中心擴充套件法求最長回文子串演算法複雜度為o 待改進 manacher方法,manacher 法將所有的字串全部變成奇數個字元。思想 回文子串一定是個中心對稱的圖形,有的對稱中心是乙個字母比如abcba,有的是對稱中心是兩個字母比如abba。所以需要分開進行 程式中會有體現 利用回文子串的這一特...