演算法,字尾陣列

2022-03-25 00:57:55 字數 1260 閱讀 4260

字尾陣列就是將字串所有字尾排序後的陣列,設字串為s,令字尾suffix(i)表示s[i..len(s)]。用兩個陣列記錄所有字尾的排序結果:

然後就是怎麼快速求所有字尾的順序了,其中的關鍵是如何減少兩個字尾比較的複雜度

方法是倍增法,定義乙個字串的k-字首為該字串的前k個字元組成的串,關於在k-字尾上的定義suffix(k,i)、sa[k,i]和rank[k,i]類似於前,則有

這樣就能在常數時間內比較suffix(2^k, i)之間的大小,從而對suffix(2^k,i)時行排序,最後

當2^k>n時,suffix(2^k, i)之間的大小即為所有字尾之間的大小

於是求出了所有字尾的排序,有什麼用呢?主要是用於求它們之間的最長公共字首(longest common prefix,lcp)

令lcp(i,j)為第i小的字尾和第j小的字尾(也就是suffix(sa[i])和suffix(sa[j]))的最長公共字首的長度,則有如下兩個性質:

對任意i<=k<=j,有lcp(i,j) = min(lcp(i,k),lcp(k,j))

lcp(i,j)=min(i

第乙個性質是顯然的,它的意義在於可以用來證明第二個性質。第二個性質的意義在於提供了乙個將lcp問題轉換為rmq問題的方法:

令height[i]=lcp(i-1,i),即height[i]代表第i小的字尾與第i-1小的字尾的lcp,則求

lcp(i,j)就等於求height[i+1]~height[j]之間的rmq

,套用rmq演算法就可以了,複雜度是預處理o(nlogn),查詢o(1)

然後height的求法要用到另乙個陣列:令h[i]=height[rank[i]],即h[i]表示suffix(i)的height值(同時height[i]就表示suffix(sa[i])的height值),則有height[i]=h[sa[i]]

然後h[i]有個性質:

用這個性質我們在計算h[i]的時候進行字尾比較時

只需從第h[i-1]位起比較

,從而總的比較的複雜度是o(n),也就是說h陣列在o(n)的時間內解決了。

求出了h

陣列,根據關係式

height[i]=h[sa[i]]

可以在o(n)

時間內求出

height

陣列,於是可以在o(n)時間內求出height陣列,

從而整個lcp問題就解決了^_^

然後字尾陣列的應用就是利用它的lcp在需要字串比較時降低複雜度。同時由於字尾陣列的有序性可以很方便地使用二分

於是總結一下要點:

演算法 字尾陣列

考完了noip,雖然d2腦子進水,然而還是目測水到了一等獎,避免了gg。也是時候開啟一些新的演算法了。思來想去,還是搞一下字尾陣列吧。先簡單說明字尾陣列,是啥。字串字尾知道吧。陣列知道吧。字尾陣列就是在將乙個字串的所有字尾按照常見的字典序排法,排一下。顯然我們可以用stdsort來進行非常暴力的排序...

演算法 字尾陣列

前言 這篇部落格真難寫,暫定待更 定義 字尾陣列 suffixarray 是乙個一維陣列,簡稱sa,它儲存1到n的某個排列 sa 1 sa 2 dots,sa n 並且保證 suffix sa i 1 leq i n 也就是將s的n個字尾按字典序從小到大進行排序之後把排好序的字尾的編號順次放入sa中...

字尾陣列 da演算法

sa陣列,他儲存1.n 的某個排列,sa 2 sa n 並且保證 suffix sa i suffix sa i 1 1 i 也就是將 s 的 n 個字尾從小到大進行排序之後把排好序的字尾的開頭位置順次放入 sa 中。rank陣列,他儲存的是每個位置的字尾子串的排名,與sa陣列是可以互逆的。heig...