字尾陣列 羅穗騫倍增演算法詳細注釋

2021-07-05 22:22:20 字數 2185 閱讀 9841

link:

#include

const

intmaxn=100010;  

intwa[maxn],wb[maxn],wv[maxn],ws[maxn];  

intcmp(

int*r,

inta,

intb,

intl)  

//就像**所說,由於末尾填了0,所以如果r[a]==r[b](實際是y[a]==y[b]),說明待合併的兩個長為j的字串,前面那個一定不包含末尾0,因而後面這個的起始位置至多在0的位置,不會再靠後了,因而不會產生陣列越界。

//da函式的引數n代表字串中字元的個數,這裡的n裡面是包括人為在字串末尾新增的那個0的,但**的圖示上並沒有畫出字串末尾的0。

//da函式的引數m代表字串中字元的取值範圍,是基數排序的乙個引數,如果原序列都是字母可以直接取128,如果原序列本身都是整數的話,則m可以取比最大的整數大1的值。

void

da(int

*r,int

*sa,

intn,

intm)  

return

;  }  

//能夠線性計算height的值的關鍵在於h(height[rank])的性質,即h[i]>=h[i-1]-1,下面具體分析一下這個不等式的由來。

//**裡面證明的部分一開始看得我雲裡霧裡,後來畫了一下終於搞明白了,我們先把要證什麼放在這:對於第i個字尾,設j=sa[rank[i] - 1],也就是說j是i的按排名來的上乙個字串,按定義來i和j的最長公共字首就是height[rank[i]],我們現在就是想知道height[rank[i]]至少是多少,而我們要證明的就是至少是height[rank[i-1]]-1。

//好啦,現在開始證吧。

//首先我們不妨設第i-1個字串(這裡以及後面指的「第?個字串」不是按字典序排名來的,是按照首字元在字串中的位置來的)按字典序排名來的前面的那個字串是第k個字串,注意k不一定是i-2,因為第k個字串是按字典序排名來的i-1前面那個,並不是指在原字串中位置在i-1前面的那個第i-2個字串。

//這時,依據height的定義,第k個字串和第i-1個字串的公共字首自然是height[rank[i-1]],現在先討論一下第k+1個字串和第i個字串的關係。

//第一種情況,第k個字串和第i-1個字串的首字元不同,那麼第k+1個字串的排名既可能在i的前面,也可能在i的後面,但沒有關係,因為height[rank[i-1]]就是0了呀,那麼無論height[rank[i]]是多少都會有height[rank[i]]>=height[rank[i-1]]-1,也就是h[i]>=h[i-1]-1。

//第二種情況,第k個字串和第i-1個字串的首字元相同,那麼由於第k+1個字串就是第k個字串去掉首字元得到的,第i個字串也是第i-1個字串去掉首字元得到的,那麼顯然第k+1個字串要排在第i個字串前面,要麼就產生矛盾了。同時,第k個字串和第i-1個字串的最長公共字首是height[rank[i-1]],那麼自然第k+1個字串和第i個字串的最長公共字首就是height[rank[i-1]]-1。

//到此為止,第二種情況的證明還沒有完,我們可以試想一下,對於比第i個字串的字典序排名更靠前的那些字串,誰和第i個字串的相似度最高(這裡說的相似度是指最長公共字首的長度)?顯然是排名緊鄰第i個字串的那個字串了呀,即sa[rank[i]-1]。也就是說sa[rank[i]]和sa[rank[i]-1]的最長公共字首至少是height[rank[i-1]]-1,那麼就有height[rank[i]]>=height[rank[i-1]]-1,也即h[i]>=h[i-1]-1。

//證明完這些之後,下面的**也就比較容易看懂了。

intrank[maxn],height[maxn];  

void

calheight(

int*r,

int*sa,

intn)  

//最後再說明一點,就是關於da和calheight的呼叫問題,實際上在「小羅」寫的源程式裡面是如下呼叫的,這樣我們也能清晰的看到da和calheight中的int n不是乙個概念,同時height陣列的值的有效範圍是height[1]~height[n]其中height[1]=0,原因就是sa[0]實際上就是我們補的那個0,所以sa[1]和sa[0]的最長公共字首自然是0。

da(r,sa,n+1,128);  

calheight(r,sa,n);  

參考自

字尾陣列 羅穗騫倍增演算法詳細注釋

include const int maxn 100010 int wa maxn wb maxn wv maxn ws maxn int cmp int r,int a,int b,int l 就像 所說,由於末尾填了0,所以如果r a r b 實際是y a y b 說明待合併的兩個長為j的字串,...

字尾陣列 倍增演算法模板

關於字尾陣列的資料,可以看noi2009國家集訓隊 羅穗騫 的 字尾陣列 處理字串的有力工具 suffix array 倍增演算法 o n lgn build sa n 1,注意n 1 getheight n n 8 num 注意num陣列最後一位值為0,其它位須大於0 rank rank 0 n ...

利用倍增演算法的字尾陣列

仍然不是很懂,貼篇文章放在這兒希望有朝一日能頓悟吧。老天,乙個字尾陣列不知道看了多少天,最後終於還是看懂了啊!最關鍵的就是一會兒下標表示排名,一會用數值表示排名繞死人了。我不知道手跑了多少次才明白過來。其實我也建議初學者手跑幾遍,但是一定要注意陣列的意義,否則就是無用功。s 輸入的字串,預處理的時候...