回文自動機學習筆記
回文自動機學習筆記
這兩天學習了回文自動機,於是在此總結一下,順便復習一下所需要的預備知識。
1 【回文串基礎】
1.1
回文串定義:長度為n,下標從0開始的字符串s是回文串,滿足\(\forall i\in \mathbb{N},s[i]=s[n-1-i]\)
1.2
\(Manacher\)算法
這裏用歸納法的方式簡介地介紹這種算法:
設\(h[i]\)表示以字符串第i個位置為中心的回文串長度。
假設已經計算出\(h[0],h[1]\dots h[i-1]\)的值。
可以由此計算出最大的回文串的右端點位置\(p\), 和右端點\(p\)對應回文中心\(pos\) 。(實際上可以直接繼承)
如果\(p \ge i\)
, 則說明在\(pos\)為中心的回文串中有一個i的鏡像位置。
如果鏡像位置的邊界和\(pos\)對應回文串的邊界不重疊,那麽位置\(h[i]\)的長度不會超過鏡像位置的長度。
如果邊界重疊,則\(h[0],h[1]\dots h[i]\)的pos和p可能被i刷新。
如果\(p < i\), 則說明在i可以刷新\(pos\)和\(p\)。
當\(p\)和\(pos\)不能被i刷新的時候,我們就可以從鏡像位置繼承\(h[i]\)的值
當\(p\)和\(pos\)可以被i刷新的時候,我們就可以同時推算出\(h[i]\)的值。
這裏p每次被刷新,只會不斷增大。所以可以證明算法的復雜度是和字符串長度呈線性關系的。
1.3
本質相同的回文子串 定義:如果兩個子串長度相同,每個位置的元素相同,則是本質相同的回文串。
一個字符串裏面,最多會有多少本質不同的回文子串?
在做\(Manacher\)的時候,只有拓展p的時候,可能產生新的回文串。(其余的回文子串一定在鏡像位置出現過),所以答案和字符串長度線性相關。
2 【回文自動機】
2.0
自動機定義自行百度
2.1
結構:
自動機中每一個點表示一種回文串,且與自動機中的其他點表示的回文串本質不同。
一個回文串可以通過在兩邊添加各一個字符,變成另外一個回文串,則這兩個回文串代表的點之間有一條有向邊,方向從短的串指向長的串。
每一個點的fail指針指向它最長的回文後綴。
每一個點上記錄回文串的長度,出現次數。
有向邊組成了兩顆樹形圖,一個表示奇數串,一個表示偶數串。
初始狀態有兩顆樹的根節點分別表示一個長度-1的串和一個空串。
2.2
構造:
假設已經構造好了第1到i-1字符的的回文自動機,並記錄右端點在i-1位置上的最長回文後綴節點,考慮添加第i個字符對它的影響。
由於我們已經構造好1到i-1所有的後綴,所有新產生的回文串一定是在位置i結尾的回文後綴。順著i-1位置的回文後綴的fail指針往回跳,路途經過的回文後綴中滿足左端點和右端點字符相同的回文串都是i結尾的回文串。
實際上我們只需要第一個左右端點相同的後綴打一個累加標記;如果這個位置是新的回文子串,則需要找到下一個回文後綴,並連上fail指針。而且根據回文串的對稱性,不需要繼續找下去了。
最後記得按拓撲序把標記依次下傳就行了。
2.3
構造回文自動機的時間復雜度
- 根據
1.3
的結論,回文自動機總點數不超過原串字符串長度。 - 構造的時間復雜度,實際上和構造時尋找合適的回文後綴時“左右端點的移動次數+ 更新fail指針的移動次數”成正比。
根據第二點,我們只需要關心這兩個東西就好了。
- 右端點移動次數:顯然右端點單調向右,移動次數N。
- 右端點每移動一次,左端點向左移動一次,所以左端點頂多向右移動2N次,向左移動N次。
- fail指針移動次數和第2點分析方式類似。
總而言之,時間復雜度O(n)
//博主老了,不想寫了,就這樣吧(生無可戀(灬°ω°灬)
2.4
模板
int s[N], ch[N][26], fail[N], len[N], cnt[N], last, ecnt, n;
void init() {
fail[0] = 1; fail[1] = 1;
len[0] = 0; len[1] = -1;
ecnt = 1; last = 1;
}
void extend( int w ) {
int p = last; s[++n] = w;
while( s[n-1-len[p]] != w )
p = fail[p];
if(!ch[p][w]) {
int u = ++ecnt, v = fail[p];
while( s[n-1-len[v]] != w ) v = fail[v];
len[u] = len[p]+2; fail[u] = ch[v][w]; ch[p][w] = u;
}
last = ch[p][w]; cnt[last]++;
}
void calc() {
for( int i = ecnt; ~i; i -- ) cnt[fail[i]] += cnt[i];
}
3 參考資料
CSDN上的一篇比較詳細的博客
跟黃學長的版對拍了一下下
還有一篇,看過但是翻不到了。。。QAQ
4 吐槽
博主原來是想把這個東西講得很細的,結果寫到一半沒了幹勁(補番去了
如果想要細節去看其他博主的博客吧o(╥﹏╥)o
當然,如果文章裏面有錯誤,但願讀者慷慨指出,多謝!
回文自動機學習筆記