馬拉車演算法是一種計算最長回文子串的演算法,以其優秀的線性複雜度聞名於世,相較於o(n
2)
o(n^2)
o(n2)的dpdp
dp演算法和會被特殊資料卡到o(n
2)
o(n^2)
o(n2
)的暴力演算法,馬拉車演算法無疑是求解最長回文子串的最優選擇。
最長回文子串分為偶數串和奇數串,為了避免這些問題,馬拉車演算法將每個字元與字元間插入乙個特殊字元,在兩頭插入不同的字元,以免越界。
馬拉車演算法定義:r
rr為當前已知的對稱的最右邊的點,mid
midmi
d為rr
r的對稱軸,f
if_i
fi為以i
ii為對稱軸的最長回文子串的回文半徑
則我們遇到乙個i
ii,分兩種情況討論
若m id
≤i≤r
mid \leq i \leq r
mid≤i≤
r,則f
if_i
fi可能為他的對稱點,即fmi
d∗2−
if_
fmid∗2
−i,但如果i+f
mid∗
2−
ii+f_
i+fmid
∗2−i
大於了r
rr,則就不能保證它的正確性,而能保證正確性的區域在哪兒呢?只有r
rr以內,所以要和r−i
+1
r-i+1
r−i+
1取乙個min
minmi
n,然而我們不能保證它的最長回文子串一定是這個範圍,所以我們要暴力拓展一下,直到不能拓展為止。
若r
r< i,那麼暴力拓展即可。 而做完這一切後,看看r rr和mid midmi d有沒有要更新的。 而我們統計答案時一定要減掉插入的字元,我們發現,統計出來的回文半徑一定是乙個奇數,則結尾是乙個# \##,將對面的對過來,得到答案為fi− 1f_i-1 fi− 1最終答案即為min (fi) −1 min(f_i)-1 min(fi )−1 那麼馬拉車演算法的時間複雜度是怎麼證明為線性呢? 若是m id ≤i≤r mid \leq i \leq r mid≤i≤ r且取值為fmi d∗2− if_ fmid∗2 −i,那麼是一定不會拓展的,因為這還在這個回文半徑裡面,兩邊肯定是相同的 而其他兩種情況,r rr是一定隨著動的。所以複雜度為線性,即o(n )o(n) o(n) **實現:#include
#include
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using
namespace std;
int n,m,k,f[
2000039
],mr,mid,ans;
char s[
2000039
],x;
intmain()
printf
("%d\n"
,ans)
;}
馬拉車演算法
思路筆記 上述情況1和情況2又可以歸結為 i 的回文半徑 和 r i的距離 中小的那個就是i的回文半徑。include include includeusing namespace std string manacherstring string str return res int min int...
馬拉車演算法
manacher char s maxn 1 int n,hw maxn 1 int l maxn 1 r maxn 1 void manacher char a n len 2 2 s n 0 int maxr 0,m 0 for int i 1 i n i manacher 題意在給定的字串中找...
馬拉車演算法
馬拉車演算法查詢 字串的最大回文子串。其演算法本質上是中心擴充套件法。中心擴充套件法 vectorv strlen,0 v i 是指以i為中心的回文字串長度的半徑 for int i 1 i strlen 1 i while str i 1 v i str i 1 v i v i 不考慮越界 而馬拉...