SA 字尾陣列

2021-08-14 21:57:48 字數 2966 閱讀 3863

首先一定要確定sa

是個什麼東西 sa

[i] 表示的是排名為

i 的字尾是哪乙個

至於字尾

i的排名是多少,那個是ra

nk[i

] 當然啦

最最最難懂的就是基數排序

要是不用基數排序,每次對於乙個二元組直接so

rt一下

這樣的複雜度是o(

nlog

2)

對於二元組的基數排序應該是這樣做的:

首先把所有元素按照最後一維丟到依次對應的桶裡面

然後順次取出

再按照第一維依次丟入

再順次取出

這樣就可以排序啦

先把**丟出來

bool cmp(int i,int j,int k)

void getsa()

}

首先,第一次做k=

0 時

相當於每個字尾的第二維都是一樣的

所以,直接按照第一維(也就是自己的值)

進行一次基數排序

接下來

每次基數排序都要利用到上一次的值

還記得吧,基數排序是先按照第二維從小往大拍

那麼,我們就先把第二維的順序搞出來

首先最小的一定就是沒有第二維的東西

所以我們先把這些數直接丟進陣列裡面

接下來就是有第二維的東西啦 第i

位的第二維是啥?ra

nk[i

+k]所以,從小到達列舉sa

,這樣保證第二維從小往大

那麼,只要sa

[i]>k

就證明它是乙個東西的第二維

所以,把sa

[i]−

k 丟到陣列裡面去就好啦

這樣的話,按照第二維就拍好啦

再來依次按照第一維丟到桶裡面去

做一遍基數排序就好啦

這樣就能夠求出sa

啦看起來很簡單誒。。

只是陣列不要搞混了

一定搞清楚每個陣列是幹啥的

比如我的** sa

是字尾陣列,sa

[i] 表示排名為

i 的串是哪乙個 ra

nk相當於排名,ra

nk[i

] 表示第

i 個串的排名 x,

y兩個陣列是記錄順序的

分別記錄第一維和第二維的排序的順序

t 是桶

這樣我們就很愉快的求出了sa

還有乙個陣列he

ight

height[

i]表示串sa

[i] 與sa

[i−1

] 的最長公共字首的長度

比如說,現在要求字尾

i 與

j的最長公共字首

那就只需要求mi

n(he

ight

[i])

,i∈[

rank

[i]+

1,ra

nk[j

]]因為已經按照字典序排好序啦he

ight

顯然可以暴力求

但是太不優美

我們有hei

ght[

rank

[i]]

>=he

ight

[ran

k[i−

1]]−

1 證明(來自hi

hoco

der )

設su

ffix

(k) 是排在su

ffix

(i−1

) 前一名的字尾,

則它們的最長公共字首是he

ight

[ran

k[i−

1]] 那麼s

uffi

x(k+

1)將排在su

ffix

(i) 的前面(這裡要求he

ight

[ran

k[i−

1]]>

1 ,如果he

ight

[ran

k[i−

1]]≤

1 ,原式顯然成立) 並且s

uffi

x(k+

1)和su

ffix

(i) 的最長公共字首是he

ight

[ran

k[i−

1]]−

1 , 所以s

uffi

x(i)

和在它前一名的字尾的最長公共字首至少是he

ight

[ran

k[i−

1]]−

1

那麼,我們按照ra

nk的順序來求he

ight

就行啦

for(int i=1;i<=n;++i)rank[sa[i]]=i;

for(int i=1,j=0;i<=n;++i)

填坑啦

最長可重疊重複k次子串

解決方法:

二分答案 每次c

heck

檢查是否有超過

k 個連續he

ight

大於二分值

最長不可重疊重複子串

解決方法:

還是二分答案

在一段連續超過二分值的he

ight

中 記錄s

a 的最大和最小值

檢查是否有重合即可

最長公共子串1

最長公共子串2

解決方法:

把所有串都接在一起

中間找乙個字典序為in

f 的字元鏈結在一起

二分乙個答案

檢查一段連續的滿足條件的he

ight

中 是否所有串都出現在一起

字尾陣列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演算法複雜一點,但...

SA 字尾陣列

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