跟風Manacher演算法整理

2022-02-19 16:22:12 字數 1585 閱讀 1454

這是上上週天機房一位神仙講的,\(gu\)了這麼久才來整理\(w\),神仙講的基本思路已經全都忘記了,幸好的是神仙寫了\(blog\),吹爆原博**\(manacher\)演算法,以及原博神仙\(ych\)!

再吹一波\(ych\):

太巨了!

\(manacher\)是一種\(o(n)\)求回文字元子串的演算法。(然後迷惑的記得當時問神仙\(ych\)乙個sha diao問題:子串是連續的嘛?顯然這裡的回文子串是連續的;

對於一串字串,對於其中的每乙個字元我們都維護乙個\(r[i]\)表示這個字串的最長回文半徑,但是這個時候出現了\(bug\):

\(ykyyky\)

\(ykykyky\)

對於前乙個子串,是偶數回文子串,而後乙個回文子串是奇數回文子串。這個時候我們該怎麼表示它們回文半徑的差別?\(3\)和\(3.5\)?✘ 這個時候我們可以在每個字串之間加『\(\#』\)

\(\#y\#k\#y\#y\#k\#y\#\)

\(\#y\#k\#y\#k\#y\#k\#y\#\)

於是這樣它們的回文半徑就唯一確定了;

看處理:\(r[i]\)表示最長回文半徑,當我們求得每個位置的\(r[i]\),當加了\('\#'\)之後,\(r[i]_-1\)就是我們要求的最長回文串長度(感性 舉例李姐

怎麼處理?

求\(r[i]\)

設前\(i-1\)個數中的回文串的右端點的最大值為\(r\),取得最大右端點的數為\(mid\)。顯然\(r=mid+r[mid]\)

\(\mathfrak.\)

\(i\leq r\)

計算\(i\)關於\(mid\)的對稱點\(j=mid*2-i\),

\(\mathfrak.\)

\(j-r[j]>mid-r[mid]\),即\(i\)的對稱點的回文串的範圍包含在\(mid\)對應點的回文串範圍,那麼\(i\)的回文串和\(j\)的回文串一定是對稱分布的(因為\(i、j\)關於\(mid\)對稱並且在\(mid\)的回文半徑內),則\(r[i]=r[j]\)

\(\mathfrak.\)

\(j-r[j]\leq mid-r[mid]\),則此時關於\(i、j\)關於\(mid\)對稱分布並且在\(mid\)回文半徑內的一定是對稱的,但是在回文半徑之外是否對稱我們不清楚,因此我們用最簡單粗暴的辦法:暴力拓展;

\(\mathfrak.i>r\)

於是暴力拓展√

在每次完成以上三項後,嘗試更新\(r、mid\):

if(r然後複雜度不會證,(一定是我太菜了.

碼量不是很大,注意字串頭尾都要插入乙個\('\#'\)

#includeusing namespace std;

char s[22000703];

int r[22000703],len;

void read()

int main ()

ans=max(ans,r[i]);

} printf("%d",ans-1);

return 0;

}

Manacher演算法總結

所謂回文串,簡單來說就是正著讀和反著讀都是一樣的字串,比如abba,noon等等,乙個字串的最長回文子串即為這個字串的子串中,是回文串的最長的那個。下面介紹manacher演算法的原理與步驟。首先,manacher演算法提供了一種巧妙地辦法,將長度為奇數的回文串和長度為偶數的回文串一起考慮,具體做法...

Manacher演算法總結

演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法 kmp和拓展kmp,這次來還是來總結乙個字串演算法,manacher演算法,我習慣叫他 馬拉車 演算法。相對於前面介紹的兩個 演算法,manacher 演算法的應用範圍要狹窄得多,但是它的思想和拓展kmp 演算法有很多共通支出,所以...

manacher演算法總結

原文 1 len陣列簡介與性質 manacher演算法用乙個輔助陣列len i 表示以字元t i 為中心的最長回文字串的最右字元到t i 的長度,比如以t i 為中心的最長回文字串是t l,r 那麼len i r i 1。對於上面的例子,可以得出len i 陣列為 2 len陣列的計算 首先從左往右...