1.新增特殊字元
通常情況下,對於乙個字串,需要求解其最長子串時,我們通常需要考慮其字元長度的奇偶性問題,比如'aba'與'abba'的求解方式不太一樣,但是馬拉松演算法在每個字元之間都新增了乙個特殊字元(原字串所沒有的),比如'#'或'$'符號,比如'aba'==>'#a#b#a#','abba'==>'#a#b#b#a#',那麼此時,無論之前字元長度是否為奇偶,現在都變成了奇數,此時我們只需要考慮這一種情況就可以了
為什麼插入特殊字元後,字串都變為奇數個字元了?
偶數情況: 假設我們有乙個偶數個字元的字串,我們令其字元數為a,此時我們為其插入特殊字元,特殊字元數為(兩邊各乙個+中間插入a-1個)如果我們令每乙個字元都與自己構成回文數,並且記錄其回文半徑(以當前字元為中心,向兩邊擴散,如果字元對稱則半徑+1,直到出現不對稱字元),比如單個字元'a'變為新字串'#a#',新字串的回文半徑將為[1,2,1],此時我們可以寫一下**即有:插入後字元個數 = a+(a-1+2
) =2a+1==> 因2a為偶數所以2a+1為奇數
奇數情況: 假設我們有乙個奇數個字元的字串,我們令其字元數為a+1,其a為偶數,此時我們插入特殊字元數為(兩邊各乙個+中間插入a個)
即有:插入後字元數=a+1+a+2
=2a+3==>2a為偶數所以2a+3為奇數
1測試一下public
static
void
test(string str)
1112
/*儲存每位字元的最大回文半徑
*/13
int len=new
int[strs.size()];
14/*
最大回文字串的中心位置
*/15
int id=0;
1617
/*遍歷新字串
*/18
for (int i = 0; i < strs.size(); i++)
2324
/*如果新查詢串更長 則替換最長回文字串的中心位置
*/25
if(len[i]>len[id]) 28}
2930
for (int i = id-(len[id]-1); i <= id+(len[id]-1); i++)
33 }
public此時我們已經能獲取到最長字串了,當然這還遠遠不能算是馬拉松演算法,見static
void
main(string args)
結果: #2#3#2#4#2#3#2#
**
1public
static
void
manacher(string str)
1112
/*儲存每位字元的最大回文半徑
*/13
int len=new
int[strs.size()];
14/*
最大回文字串的中心位置
*/15
int id=0;
16/*
最大回文字串的右邊界
*/17
int mxindex=0;
1819
/*遍歷新字串
*/20
for (int i = 0; i < strs.size(); i++) else
if(len[j]>mxindex-i) else
if(len[j]==mxindex-i) 48}
4950
51while(i-len[i]>=0&&i+len[i]len[i]))
5455
/*如果新查詢串更長 則替換最長回文字串的中心位置
*/56
if(len[i]>len[id]) 60}
6162
for (int i = id-(len[id]-1); i <= id+(len[id]-1); i++) 65}
66
演算法馬拉松24
n 1個點的多邊形。給外圈的邊標記上1 n,裡圈的邊也標記上1 n,使得對於乙個外圈相鄰點與中間點構成的三角形的邊權之和都相等。n le 10 6 顯然每個三角形權值和為 frac 一開始簡化成n個數排乙個環,相鄰兩個數的和不相等並且有上下界,然後並不好做 構造了一下n 5發現外圈正好1.5,內圈1...
最長回文子串(馬拉車演算法)
最長回文子串,即正反讀起來都一樣,例如 ababa manacher algorithm演算法利用了回文的重複特性,讓時間複雜度降為了o n 馬拉車演算法詳解 改造字串,在中心擴充套件法中,要求區分字串長度為奇數或偶數的情況,我們這裡對字串進行簡單的改造,讓字串變成奇數便於處理。例 ababad a...
Manacher馬拉車演算法求最長回文子串
終於把馬拉車演算法搞明白了!趕緊記錄一下,以後忘記了還能再回憶起來。這個演算法用於查詢乙個字串的最長回文子串 馬拉車演算法依次給陣列p i 賦值,馬拉車演算法的本質就是在每次給陣列p i 賦值時嘗試進行偷懶 例如,當要給p 6 賦值時,前面分別以 p 0 p 1 p 2 p 3 p 4 p 5 為中...