學習筆記 Manacher與PAM

2022-03-13 08:48:14 字數 1504 閱讀 8360

挺短,背是挺好背的

manacher用於求回文串長度。思想大概就是:

1、加入字符集之外的識別字元(比如#)分隔開原來相鄰的字母,這樣所有的回文串都變成了以某個字元為中心的(否則如果是偶數長度的回文串還要特判)。

2、考慮藉由以前的資訊求出新的回文串長度。記錄到現在為止最靠右的回文串中最右側的字元下標&其對稱軸的下標,不妨記這個最靠右的串為\(\rm s\)。那麼考慮以當前位置作為對稱軸的答案,一定至少是\(\min\)。然後就不斷擴充套件即可。

3、關於複雜度證明。我們記一次帥氣的操作的意義是成功讓\(ans_i\)的初始值繼承了與之對稱的點的答案和邊界的取\(\min\),記以當前點為軸的最長回文子串為\(\rm t\),\(t\)的右端點為\(q\)。可以知道

so,最終複雜度就是\(\theta(n)\)的。

void manacher(char *s)

}int main()

學了pam,不知道為啥感覺比sam簡單?參考的資料會放在最後。

其實就是一種自動機,以回文串為狀態,左右各新增乙個字元為轉移的自動機。要點如下:

0、乙個串的回文子串至多有\(o(n)\)個。

1、首先每個節點需要儲存這個節點中回文串的長度。

2、顯然始狀態需要有兩個,即奇數長度的\(s\)和偶數長度的\(s\),稱作「奇根」「偶根」。那麼為了方便呢,奇根的長度設定為\(-1\),偶根長度設定為\(0\)。

3、考慮要從\(last\)指標擴充套件當前狀態,假設當前需要insert的字母是\(c\),是這個串裡面的第\(p\)個字元,那我們需要找到乙個字尾\(s[j...p-1]\quad s.t.\quad s[j...p-1]\)本身回文且\(s[j-1]=c\),那麼就可以向下擴充套件。

4、考慮怎麼找這個字尾,顯然對於乙個串\(s\),他的所有回文字尾都是其最長回文字尾的回文字尾。所以考慮\(fail\)指標,應當從當前狀態連向它的最長回文字尾

5、插入新節點時,考慮跳完\(fail\)後如果沒有相應的轉移邊,就要新建乙個狀態然後連\(fail\).

然後是**和一點注意:

struct pamp ;

void _init(pam &p)

void _insert(pam &p, int x, int pos, char *s)

p.last = p.trie[u][x] ;

}

6、\(\rm \color\),以下兩句順序不要寫反:

p.fail[newn] = p.trie[fa][x], p.trie[u][x] = newn,
原因是當\(fa=u\)時就出現環了。

學完才知道,\(\rm pam\)又簡單又好背功能又多……manacher被打爆了啊喂qwq。

manacher 學習筆記

部分內容 因為剛開始學,所以有些可能講解的不是特別好。manacher演算法 民間稱馬拉車演算法233 是用來找字元 串中的最長回文子串的,先來說一下什麼是回文串,像這樣 abcba 這樣乙個字串找到乙個中間位置,然後分別向他的左邊和右邊相等的距離位置的字元是相同的,那麼這個字串就稱為回文串,abc...

Manacher學習筆記

目錄manacher演算法 可在 o n 的時間內求出乙個字串以每個位置為中心的最長回文子串。原理 根據之前預處理出的回文串長度求得新的回文串長度 我們可以通過在字元中加上 來避免長度為偶數回文串沒有中心的問題 原串 abcd 變為 新串 a b c d 原串中長度為奇數和偶數的回文串的長度均變為奇...

學習筆記 Manacher演算法

manacher 中文 馬拉車 演算法,即求解給定字串中最長回文子串長度的演算法。洛谷p3805 給出乙個長度為 n 的只由小寫英文本元 mathtt 組成的字串 s 求 s 中最長回文串的長度 一般情況下回文串有奇偶分類。為了避免分類,我們在字串中間新增特殊字元 不妨用 在串的首尾加上不同的特殊字...