SA 字尾陣列 專題總結

2022-02-03 12:07:04 字數 2186 閱讀 9062

曾經一度以為sa是大神知識點來著

後來才發現其實是澤州哥哥講得太深奧了我等蒟蒻不能參透

理解了之後題還是可以做的

因為大多數都不是在sa上做文章而是與其他知識點結合

(\(\% \% \%\)迪哥講 \(sa\) 和 \(sam\) 鈦聚啦)

放例題

算是sa的板子題了吧

求出每個點能控制的區間,單調棧\(/\)二分都行,直接統計就行了

sa乙個套路就是把所有串連起來然後一塊跑

這題要求有相同的趨勢,顯然需要差分

那麼我們把原字串差分之後連在一起跑一遍sa

又發現答案顯然有單調性,可以二分

那麼我們直接看是否有乙個 \(height\) 始終\(>mid\) 的區間包含所有串就行了

把所有名,姓和詢問串連起來跑一遍$ sa$,求出每個詢問串能控制的區間

然後問題就變成了詢問區間內顏色個數以及每種顏色被多少種區間覆蓋

直接求不容易處理,考慮莫隊

第一問是板子,不講

第二問,只要在某種顏色出現時記錄一下,然後在消失時統計答案就行了

發現答案滿足單調性可以二分

現在考慮詢問某個串的子串中是否有和 \(s[c,d]\) 的 \(lcp\ge mid\) 的串

而我們可以很容易得到和乙個串 \(lcp\ge mid\) 的 \(rk\) 區間 \([l,r]\)

那麼我們只需要統計\([a,b-mid+1]\)中是否有排名\([l,r]\)之間的點了

這個可以主席樹維護

首先,乙個串本質不同子串個數為\(\sum\limits_^n n-sa[i]-height[i]\)且單調遞增

那麼對於某個排名,我們可以二分出該串屬於的字尾以及長度

這樣就可以求 \(lcp\) 和 \(lcs\) 了

考慮由低相似度\(i\)轉到高相似度\(i+1\)

發現相當與在所有 \(height=i\) 的點把序列斷開

然後發現總共的斷開操作有n次

所以我們從小到大列舉相似度,鍊錶\(/ set\) 維護分界點

每次插入乙個分界點時,二分找到他兩邊的分界點,把之前區間的貢獻減掉,再把新區間的貢獻加上

然後計算貢獻我們需要找區間最大,次大,最小,次小值,用 \(rmq\) 可以 \(o(1)\) 得到

這個東西怎麼看怎麼像單調棧

我們排序後求出所有\(b[i]=lcp(a[i],a[i+1]) \ (1\ge i

用 \(b\) 陣列做單調棧,求出控制區間,就可以直接統計答案了

大神題啊

首先這個萬意顯然是單調的,可以二分

我們知道有了排名可以唯一確定乙個子串t

那麼我們二分排名,得到了這個排名的子串,考慮怎麼 \(check\)

我們從後往前貪心,發現如果之前是合法的,那麼當且僅當s[i,lst]合法時目前狀態合法

那麼我們只需要比較s[i,lst]和t的大小關係

這個東西可以用rmq弄出來

(並不知道思路是怎麼想到的)

考慮設定關鍵點

首先列舉a的長度l,然後在 \(1,1+l,1+2l\)......設定關鍵點

然後對於每個關鍵點 \(i\),求出 \(i\) 和 \(i+m+l\) 的 \(lcp\) 和 \(lcs\)

發現所有和 \([i-lcs,i+lcp],[i+m+l-lcs,i+m+l+lcp]\) 同時有交的長度為 \(m\) 的區間都會貢獻答案

這個答案為 \(min(min(l,lcp)+min(l,lcs))-l\)

又因為同一長度下乙個區間被且僅被乙個關鍵點經過

所以這樣可以做到不重不漏

SA 字尾陣列

首先一定要確定sa 是個什麼東西 sa i 表示的是排名為 i 的字尾是哪乙個 至於字尾 i的排名是多少,那個是ra nk i 當然啦 最最最難懂的就是基數排序 要是不用基數排序,每次對於乙個二元組直接so rt一下 這樣的複雜度是o nlog 2 對於二元組的基數排序應該是這樣做的 首先把所有元素...

字尾陣列SA

給定乙個字串s,按字典序排序s的所有子串 鬼知道什麼思想,好像沒有什麼思想。哦,想起來了,是倍增。考慮最簡單的字尾間o n o n 比較和快排o nlog n o n logn 總複雜度o n2lo gn o n 2log n 考慮優化字串間的比較,用倍增的思想,假設k 2 k 2 長度的已經比完了...

字尾陣列SA

原理 其本質就是把字串的所有字尾進行排序。用普通排序需要o nlogn 但是字串比較和數字比較不同,所以實際需要o n nlogn 為了讓這個過程快一點,所以有了倍增演算法,o nlogn 和dc3演算法,o n 倍增演算法比較簡單,也比較好寫,具體可以參考這個大佬的部落格。dc3演算法複雜一點,但...