自己看的Manacher

2021-10-09 09:04:25 字數 3536 閱讀 4146

1.問題引入

最長回文子串:即在給定的串中找到乙個子串,該子串是回文串且長度最長。回文串即對稱串。

舉例:s = 「abadaba」,回文子串有"aba",「abadaba」,而最大的即是s本身

2.常規方法

<1>暴力演算法(o(n3))

暴力列舉每乙個子串,判斷是否為回文串。若是,記錄並更新長度;若不是,則跳過。

#include

#include

#include

using

namespace std;

bool

judge

(string s)

return i >= j;

}int

main()

}if(flag)

break;}

if(plen)

return0;

}在這裡插入**片

<2>.中心擴充套件(o(n2))

中心擴充套件(有些地方也叫dp?):簡言之,對於串的每乙個位置為中心,向左右兩邊擴充套件(判斷兩端是否相等),記錄並更新長度。(這裡帶來了個問題,中心可能會是兩個字元間的位置)

#include

#include

#include

#include

using

namespace std;

intlongestpalindromelenth

(string s,

int&plen,

int&fir)

if(rp - lp -

1> ret)

}//兩個中心擴充套件

for(

int i =

0; i < s.

length()

-1; i++)if

(rp - lp -

1> ret)

}return ret;

}int

main()

3.manacher(o(n))

引言:macher是如何做到線性複雜度處理最長回文字串的呢?最重要的是利用了回文串的特點即左右對稱

在暴力演算法中我們沒有考慮到對稱中心這個因素,在中心對稱演算法中則是利用了這一點;而在manacher演算法中,由於中心擴充套件演算法中並未對各個對稱中心間的關係進行優化(即在前乙個對稱中心擴充套件的整個回文區間可能會包含後乙個中心擴充套件的回文區間),正是利用這一點manacher進行了優化。

<1>lps(longestpalindromestring)陣列

que:如何統一奇偶對稱中心?

ans: 在每個字元左右加乙個特殊字元。

ex:stringab

abab

alps$a$

b$a$

b$a$

b$alps[pos] = d含義: 在當前位置能向左右擴充套件的最大位數

lps$a$

b$a$

b$a$

b$a$

pos012

3456

78910

1112

1314

exlenth010

3050

7050

3010

center:當前對稱中心

ileft: 關於對稱中心對稱的左對稱中心

i: 需要計算的對稱中心

lb:向左擴充套件的邊界

rb:向右擴充套件的邊界

que0:什麼時候可以從直接求得的lps[pre]求出當前的lps[i]的值?

ans0:通過對稱的點擴充套件長度擴充套件並未達到右邊界。

i + lps[il] < rb

既然存在i + lps[il] < rb,則必存在i + lps[il] >= rb的,此時必有lps[i]>=rb - i;此時需要看能否繼續擴充套件,所以剩下的就是中心擴充套件演算法

#include

#include

#include

using

namespace std;

#define maxn 2000000 + 100

int lps[

2*maxn]

;char s[maxn]

;char exs[maxn*2]

;int

manacher

(char s)

//字串處理

int rb =

1,lb =

1,center =

1,il =0;

lps[0]

= lps[

2*len]=0

;//首尾特殊處理

int ret =1;

for(

int i =

1;i <

2*len;i++)if

(crb > rb)

ret =

max(lps[i]

,ret);}

return ret;

}int

main()

return0;

}

主要參考了geekforgeeks上的教程

英文基礎好的可以看:geekforgeeks manacher

網上模板
#include

#include

#include

#include

using

namespace std;

char s[

11000002];

char s_new[

21000002];

//存新增字元後的字串

int p[

21000002];

intinit()

s_new[j]

='\0'

;//處理邊界,防止越界(容易忘記)

return j;

// 返回s_new的長度

}int

manacher()

max_len=

max(max_len,p[i]-1

);}return max_len;

}int

main()

寫給自己看的

我不常寫日誌,不過最近各種事情,還是有點需要記錄下來。今天下午上資料庫的時候,本來以為被鄙視了的 筆試居然發來恭喜通過的通知,說是等待面試,出乎意料的同時也感嘆rp又用掉了很多 最近的rp消耗確實有點失常,painterbee在mm上的表現就不說了,在校賽上也拿到了之前沒拿過的高名次,雖然是題目的區...

整理,自己看

時間管理十條 1 每週做回顧並做下週計畫 2 嚴格自律 3 時間花在有成果的行為和對話 4 為突發狀況預留時間 5 每天花半小時做計畫 6 做事前花5分鐘確認想要結果 7 重要工作排除一切外部干擾 8 別忙著接 回郵件除非是vip客戶 9 遮蔽社交 10 你不是超人,不可能完成所有事。如何提公升個人...

回看之前的自己

最近有換工作的傾向,所以一直在網上看一些面試題,斷斷續續整理了一些,準備整理完畢後開啟死記硬背模式。因為自己的語言表達能力比較弱,所以一直覺得面試前的背誦是很有必要。遇到別人分享的一些面試心得 學習歷程之類的也視若寶典,企圖從中揣摩一二良言,使自己能夠學習參考。然而到底學到了什麼,現在也說不上來。現...