日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Manacher入门

發(fā)布時(shí)間:2023/12/3 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Manacher入门 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

寫在前面

manachermanachermanacher比想象中好理解得多

至少它給了我學(xué)習(xí)字符串的信心

能干啥

manachermanachermanacher,中文馬拉車(您別說,這名字還挺形象),主要用于計(jì)算字符串每一個(gè)位置為對(duì)稱中心的回文串長(zhǎng)度(等價(jià)于個(gè)數(shù))

包括偶回文,即長(zhǎng)度為偶數(shù)的回文串

算法流程

考慮下面的問題:給一個(gè)字符串,求最長(zhǎng)回文子串

我會(huì)暴力!

枚舉判斷O(n3)O(n^3)O(n3)

我會(huì)優(yōu)化!

考慮到以ccc為中心,acbacbacb不是回文串,左右怎么接都不是回文串

所以可以枚舉中間點(diǎn)(偶回文判斷一下即可),然后向兩邊拓展

復(fù)雜度O(n2)O(n^2)O(n2)

我會(huì)玄學(xué)!

O(n2)O(n^2)O(n2)還不夠 不符合字符串算法均為線性復(fù)雜度公理

在此基礎(chǔ)上繼續(xù)優(yōu)化

我們記錄maxrmaxrmaxr為目前找到的回文串右端點(diǎn)的最右的位置 pospospos為這個(gè)回文串的對(duì)稱中心

開一個(gè)數(shù)組pip_ipi?表示回文半徑(和其他文章不同,本文回文半徑指一個(gè)端點(diǎn)到中心的距離,即直接相減)

回文串最本質(zhì)的特征是什么?左右關(guān)于中心對(duì)稱。

如果一個(gè)回文串對(duì)稱中心的一側(cè)有另一個(gè)回文子串,那么對(duì)稱過去也有一個(gè)相同長(zhǎng)度的回文子串


黃色部分完全一致,這就是manacher的核心

(先不考慮偶回文)

i&lt;maxri&lt;maxri<maxr(取不取等于無所謂)

設(shè)j,ij,ij,i關(guān)于pospospos對(duì)稱 即j=pos?2?ij=pos*2-ij=pos?2?i

根據(jù)上面的推導(dǎo),令pi=pjp_i=p_jpi?=pj?即可

當(dāng)然如果jjj為中心的最長(zhǎng)回文左端點(diǎn)越界了

那就不能保證上面的性質(zhì)(實(shí)際上可以保證不成立),所以要和j?maxlj-maxlj?maxl(即maxr?imaxr-imaxr?i)取minminmin

jjj越界時(shí)還需要讓iii繼續(xù)拓展。當(dāng)然為了刷短代碼減少討論,都拓展一下好了

i≥maxri \geq maxrimaxr


啥都不能保證,直接暴力擴(kuò)展

綜上:

  • 如果i&lt;maxri&lt;maxri<maxr,按上述條件更新pip_ipi?
  • 暴力拓展
  • 更新maxrmaxrmaxrpospospos
  • 然后……對(duì),沒了,就三行。

    這就是manachermanachermanacher的全過程,復(fù)雜度O(n)O(n)O(n),后面有證明

    實(shí)現(xiàn)

    上面沒有討論偶回文,主要是轉(zhuǎn)化過程比較難看,容易使人喪失信心。

    其實(shí)也不難。只需要在字符兩兩之間加一個(gè)字符,如‘#’;然后首尾也加上‘#’,再在開頭加一個(gè)標(biāo)識(shí)符防止越界。注意要和之前的不同,如‘@’

    這樣偶回文可以看做中心是‘#’的回文

    普及T1模擬水平

    這樣處理后,所有回文串左右端點(diǎn)都是‘#’,然后就可以跑了

    證明

    什么?不是只改了一個(gè)地方嗎?怎么變O(n)O(n)O(n)了?

    回顧整個(gè)流程,真正暴力拓展的時(shí)候要么jjj左端點(diǎn)越界,要么iii越界(jjj左端點(diǎn)沒越界時(shí),根據(jù)反證法,iii實(shí)際上無法拓展)

    jjj左端點(diǎn)越界時(shí),iii右端點(diǎn)出生點(diǎn)就在maxrmaxrmaxr,再拓展就超出去了

    也就是說,每次暴力拓展,都意味著maxrmaxrmaxr更新,而maxrmaxrmaxr只會(huì)往右跑

    換一個(gè)角度,實(shí)際上暴力拓展是把maxrmaxrmaxr推到最右邊,次數(shù)是O(n)O(n)O(n)

    所以總復(fù)雜度是O(n)O(n)O(n)

    代碼

    #include <iostream> #include <cstdio> #include <cstring> #define MAXN 1000005 using namespace std; char s[MAXN],ss[MAXN]; int pos,maxr; int p[MAXN]; int main() {scanf("%s",s+1);int n=strlen(s+1);for (int i=1;i<=n;i++) ss[i<<1]=s[i],ss[(i<<1)|1]='#';n=(n<<1)|1,ss[0]='@',ss[1]='#';strcpy(s,ss);for (int i=1;i<=n;i++){if (i<maxr) p[i]=min(p[(pos<<1)-i],maxr-i);while (s[i-p[i]-1]==s[i+p[i]+1]) ++p[i];if (i+p[i]>maxr) maxr=i+p[i],pos=i;}return 0; }

    由于所有位置為中心的最長(zhǎng)回文串左右端點(diǎn)都是‘#’

    回文串長(zhǎng)度leni=2pi+1?12=pilen_i= \frac {2p_i+1-1}{2} = p_ileni?=22pi?+1?1?=pi?

    然后用來搞事情就可以了

    總結(jié)

    以上是生活随笔為你收集整理的Manacher入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。