又是刷oj的一天。
上題
題意很簡單,求出最長的回文子串,暴力試一下? 從每個字元開始雙向擴充套件,記錄最長回文子串。對於1e6的資料量,時間複雜度為o(n*n)的演算法,可以直接pass了。那麼又有什麼好的辦法來解決最長回文子串的問題呢?答案就是——manacher馬拉車演算法。這個演算法十分巧妙。可以在o(n)的時間複雜度內求出答案。那麼他是怎麼實現的呢?我們一起來看一下題目描述:
jiangyu有乙個長度為n的僅包含小寫字母的字串。他想找出其中最長的回文子串。。
輸入:乙個字串s,∣s∣≤1e6
輸出:乙個整數,最長回文子串長度
樣例輸入
caaaaab
樣例輸出
5
首先我們在求回文子串時候存在乙個問題,就是子串長度為奇和偶數的時候是不太一樣的。所以我們必須分開討論,為了避免分枝,我們要想乙個辦法,將奇子串和偶子串和為一種情況來討論。方法如下:
將原字串的字元之間填充符號#,就是將
aca 變為 #a#c#a#
acmmca 變為 #a#c#m#m#c#a#
這樣所有的回文串的長度都變成了奇數,就不用再分情況討論了。
可是這樣加完填充符號以後,如何知道原先回文子串的長度呢,這時我們引入回文半徑r,使用乙個r陣列,r[i]表示該字元為中心的最長回文子串的半徑。對於acmmca來說,長度為6,對於增加完填充字元以後,最中間的#字元的回文半徑為7。和原回文串的長度相差1。這是乙個普遍規律
r[i] - 1正好是原字串中最長回文串的長度
所以現在問題就轉化為,求所有r[i]中最大的,將其減1就是最長回文子串的長度。
那麼怎麼求r[i]呢?
首先引入兩個變數id和mx
id為目前為基準字串的下標值
mx就是以id為中心的最長回文子串可以延伸到的最遠距離
以id為基準,如果求i為中心的最長回文子串,如果i > mx ,則老老實實求,如果i < mx,我們可以找到i關於id的對稱的j ,如果r[j]<=mx-i,因為在mx範圍內,所以r[i]的值等於r[j],最長回文子串長度相同。
如果r[j]>mx-i,不能保證i在mx之後還是不是回文的,但是最起碼在i~mx之間還是回文的,那麼i的回文長度最起碼是mx-i所有r[i] = mx - i;
有了這個思想,演算法就不難寫出來了。
演算法比較簡單,到這裡就結束了,交一發#include
using namespace std;
int r[
2000000];
string s;
inthw()
int id=
0,mx=
0,ans =1;
for(
int i=
1;ilength()
;i++
) ans =
max(ans,r[i]-1
);}return ans;
}int
main()
完美ac,開心的去吃飯
O n 時間求 最長回文子串 Manacher演算法
回文字串分為奇回文和偶回文,在字串中間插入任意字元使得串變成奇回文串 暴力思想 肯定是找乙個點往兩邊任意擴充套件,遍歷一次,manacher時間為o n 開乙個陣列p記錄 以點i為中點 的最長回文串的半徑,假設前i 1個點的p都已經求出來來,現在考慮p i 如何推導 重點 r是p 1 p i 1 中...
Manacher 最長回文子串
最長回文子串問題 給定乙個字串,求它的最長回文子串長度。如果乙個字串正著讀和反著讀是一樣的,那它就是回文串。下面是一些回文串的例項 12321 a aba abba aaaa tattarrattat 牛津英語詞典中最長的回文單詞 對於最長回文子串問題,最簡單粗暴的辦法是 找到字串的所有子串,遍歷每...
Manacher 最長回文子串
caioj任意門 hz2016評測傳送門 可以的話來一下hz2016評測吧,有的題caioj沒有的我也可以給到資料嘛。include include include include include include include include define maxchar 100000 defin...