Manacher Algorithm 最長回文子串

2022-09-03 07:33:13 字數 1356 閱讀 3317

列舉子串(起點和終點),再判斷子串是否回文串。時間複雜度o(n^3)

列舉子串的中點,從中點向兩側擴充套件判斷回文串。時間複雜度o(n^2)

在前一種演算法的基礎上再加以改進,達到o(n)的時間複雜度

首先考慮乙個問題:長度為奇數的字串的中心是中間那個字元的位置,而長度為偶數的字串的中心是中間兩個字串之間的「縫隙」。列舉偶數長度的回文子串的中點,似乎不好處理(如何能列舉乙個「縫隙」的位置呢?)

既然這樣,設法做一種預處理,在原字串s的間隙插入特殊字元,例如'#'(包括首尾),得到新字串t

例如:s:    abcba

t:     #a#b#c#b#a#

這樣,列舉到'#'就表示列舉到偶數長度的子串的中點了

回文半徑:回文串最右字元與回文中心字元的距離。以t[i]為中心的回文子串t[l,r],其回文半徑為r-i+1

例如:aba的回文半徑為2

輔助陣列len:len[i]表示字串t中以第i個字元為中心的回文子串的回文半徑

可知len[i]-1就是該回文子串在原字串s中的長度

證明:首先,在字串t中,該回文子串長度是2*len[i]-1,以#開頭且以#結尾;不妨先「去掉」開頭或結尾的乙個#,剩下的部分長度是2*len[i]-2,其中一半是原串s中的字元,一半是#,所以該子串在原串s中的長度就是len[i]-1

輔助變數pos和maxright:maxright是當前已知的所有回文子串的右端點能延伸到的最大值,取得這個最大值的回文串的中點是pos

從左往右依次計算len[i],設j是i關於pos的對稱點,有(j+i)/2 = pos,j = 2*pos - i(j討論i的位置與maxright的相對關係:

當i<=maxright:

考慮len[j],若len[j] <= maxright-i+1,則len[i] = len[j];否則len[i]的最小值是maxright-i+1(從maxright+1開始向右還可能再延伸以t[i]為中心的回文串長度)

當i>maxright:

此時len[i]無法如前所述地利用之前已經求得的資訊了,故只能從t[i]像左右擴充套件尋找最長回文長度

maxright只會一直向右推移,i>maxright時,對於乙個字元t[i],它影響maxright,使maxright向右推移,此時我們進行了回文串的左右匹配過程;但是當i4.**實現

1

int manacher(string &s)219

return

maxlen;

20 }

ps:如果要求最長回文串,那麼在過程中記錄下在字串t中的maxlen對應的idx和len[idx]即可。(最長回文子串是t[idx-len[idx]+1, idx+len[idx]-1]中不為'#'的子串行組成的字串)

最長回文子串 最長回文子串行

1.最長回文子串行 可以不連續 include include include include using namespace std 遞迴方法,求解最長回文子串行 intlps char str,int i,int j intmain include include include using n...

最長回文子串與最長回文子串行

題目1 求最長回文子串 題目2 求回文子串數量 忽略兩個題目對於返回結果的不同要求 前者返回最長的結果,後者返回最長的結果對應的長度即可 dp陣列的定義的區別 最長回文子串 dp i j 表示的是string s中從i到j的子串 用python語法就是s i j 1 是否為回文子串。最長回文子串行 ...

最長回文子串 LeetCode 五 最長回文子串

題目 最長回文子串 給定乙個字串s,找到s中最長的回文子串。你可以假設s的最大長度為 1000。題目解析 回文?當回文串長度為奇數時,比如 北京計程車租出京北 當回文串長度為偶數的時候,比如 1221 以上兩種情況有乙個共同的特點就是有乙個中心,那在 中如何表示中心呢?class solution ...