進入正題,manacher演算法是乙個高效的計算回文串的演算法,回文串如果不知道可以給出乙個例子:「 noon 」,這樣應該就很清晰了;
其實這個演算法雖然名字長,但是實際**很短,而且理解起來並不難。。。(連我這種蒟蒻都懂了)
這裡給出模板題
給出乙個只由小寫英文本元a,b,c...y,z組成的字串s,求s中最長回文串的長度.
字串長度為n
一行小寫英文本元a,b,c...y,z組成的字串s
乙個整數表示答案
其中n的範圍為11000000,很顯然,只能是o(n)的複雜度,但是為何複雜度這麼優秀,這裡在講完演算法之後會簡述。
定理:
解釋:
上面的原理畢竟太過幹,只是純理論,所以製圖說明;
比如說這個區間是乙個大回文串,我們我們用r保留其有邊界,那麼l就可以根據中點座標公式變形得到mid*2 - r,所以我們只保留右邊界 r 即可。
那麼可以看見,如果我們以 i 為這段區間中乙個回文串的中心,那麼,與它對稱的回文串中心就可以求出(根據中點公式,得2*mid - i ,與上面相同);
那麼我們就可以根據定理來繼承左邊回文串的半徑,但是如果左邊這個回文串有超過區間的部分怎麼辦?
這裡就用到我們所說的取min了,將左邊回文串半徑和r - i相比取min,這裡就得到了 i 的乙個半徑,但這個半徑一定小於或等於真實半徑,所以還需暴力列舉;
這裡就可見manachar演算法的核心操作了,就是列舉回文串中心,然後繼承半徑以來減少列舉的次數;
我們用p[ i ]表示以點 i 為中心的回文串的半徑,r記錄回文串到達的最右邊的座標,mid隨之更新,記錄這個回文串的中心;
code
#include#define maxn 22000007這就是manachar演算法的簡述了,當然這裡解釋一下為什麼複雜度為o(n):using
namespace
std;
char
dat[maxn];
int p[maxn],r,cnt=1
,mid,ans;
void
scan()
//其實與讀入優化沒差啦
}//自定義讀入
intmain()
printf(
"%d\n
",ans-1);//
這個減一可以自己模擬一下,數學推了話好麻煩的說
}
我感覺這和kmp複雜度有些類似,因為這裡因為繼承的緣故,所以每個點更新次數較少,然後均攤到每個迴圈,那麼複雜度就變成了o(n)了;
(回文串)Manacher演算法
標籤 acm 回文串 manacher 輸入乙個字串,求出其中最大的回文子串。子串的含義是 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。這裡介紹o n 回文子串 manacher 演算法 演算法基本要點 首先用乙個非常巧妙的方式,將所有可能的奇數 偶數長度的...
(Manacher)演算法 O n 回文子串
資料 網路 參見 問題描述 輸入乙個字串,求出其中最大的回文子串。子串的含義是 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。解析 這裡介紹o n 回文子串 manacher 演算法 演算法基本要點 首先用乙個非常巧妙的方式,將所有可能的奇數 偶數長度的回文子...
O n 求回文串 manacher演算法
p id 2 i 代表的是關於i關於id對稱的點j,陣列p i 1代表插入字元後一i問對稱的回文串的長度 資料 網路 參見 問題描述 輸入乙個字串,求出其中最大的回文子串。子串的含義是 在原串中連續出現的字串片段。回文的含義是 正著看和倒著看相同,如abba和yyxyy。解析 這裡介紹o n 回文子...