省選演算法學習 字尾陣列 字尾自動機 字尾樹

2022-03-07 05:42:13 字數 1575 閱讀 1671

其實很久以前就學了這兩個東西......但是一直懶得寫,今天補一補

基礎部分不講了,放個板子在這

void bsort()

void getsa()

k=0;

for(i=1;i<=n;height[rank[i++]]=k)

for((k?k--:k),j=sa[rank[i]-1];a[i+k]==a[j+k];k++);

}

應用嘛,還是很廣泛的

本體可以字尾排序【廢話】

求出height並且st表一下,就可以求內部lcp啦之類的,還可以套主席樹使用

多串的時候可以考慮首尾相連中間加分隔符'$'然後建sa,操作也很多

聽說還能套fft一起用?我反正沒見過

套主席樹的

套可持久化線段樹的:十二省聯考2019 字串(雖然實際上是sam題)

別的懶得放了......很多操作現想就好

candy?菊苣講的非常好,放在這裡:candy?

理解稍微有點困難......但是把有些概念當顯然成立的背下來會有很大幫助

每個節點上$right$集合是核心維護的東西,維護的是這個節點可以識別的子串的可能起點

對於每個節點$s$,都有乙個範圍$[min(s),max(s)]$

從$right$集合中的位置出發,長度在這個範圍內的子串,被sam識別以後就放在這個點!

sam也有fail樹,其實更常見叫$parent$ $tree$,相當於失配指標

對於節點$fa$和節點$s$,有性質:$max(fa)=min(s)-1$

同時,$right(fa)$是所有包含$right(s)$的集合中,最小的乙個

兩個基本用法:

往對應的兒子走,就是匹配串後面加個字元

往自己的fail走,就是匹配串前面刪個字元

板子在這裡

namespace sam

inline int newnode(int w)

void insert(int c)

} last=np;

} void sort(int n)

}}

廣義的東西,就是把很多串建成$trie$然後$bfs$插入,要記錄$last$指標下來

$right$集合裡很多資訊都可以維護,不止大小,還可以狀壓維護屬於哪個串之類的

然後,有個操作是不做最後面那個基數排序,而是每次插入完從$np$往上更新$siz$,遇到更新過的就$break$

這種時間複雜度上界好像是$o(nlogn)$,資料小(1e5)的可以用用,不要老是用

$fail$樹可以套到$lct$上,然後可以動態加元素、動態$dp$之類的

建立反串的sam,其parent樹就是原串的字尾樹!

對於乙個子串$[l,r]$,可以用在字尾樹上倍增的方式快速定位。

具體而言,我們每一次完成插入的時候記錄$last$指向的節點:那個節點就是對應的字尾在字尾樹上的位置

倍增的時候,從$l$對應的節點開始倍增,找到最淺的,$right$集合適應區間包含$r-l+1$的節點,就是這個子串在字尾樹or字尾自動機上的位置

模板 字尾陣列 字尾自動機

關於字尾自動機sam,貼乙個非常好的講解 字尾自動機學習小記 交洛谷模板可a 傳送門 洛谷 模板 字尾排序 include using namespace std const int n 1e6 5 char s n int sa n t1 n t2 n c n int n,m 555 void s...

字尾陣列與字尾自動機學習筆記

這只是個人小結,沒啥大意義。字尾陣列 其實就是通過把字串的所有字尾排序來實現一些東西。字尾排序可以用倍增 雙關鍵字來實現。然後排完之後可以求出height陣列,然後就可以用rmq求lca了。字尾自動機 各種複雜度都是線性的,非常優秀。原理 把具有相同right集合的狀態縮成乙個點,這個點內的所有狀態...

字尾自動機學習

今天終於把這週的坑填了,同樣看了很多部落格,這裡就不詳細總結了,就簡單整理一下了。應用 1 存在性查詢 給定文字t,詢問格式如下 給定字串p,問p是否是t的子串。直接按著路徑走,看是否存在即可 2 不同的子串個數 對於每乙個節點即為 len i len fa i 加和即可 3 不同子串的總長 這裡我...