高度陣列與最長公共字首

2021-09-25 20:52:08 字數 1694 閱讀 6110

摘要

本文是關於字尾陣列的乙個拓展,問題模型來自於最長公共字首(longest common prefix array)問題,我們為解決該模型,在字尾陣列的基礎上設計了乙個精巧的陣列——高度陣列,同時由於該陣列在處理各類字串相關問題時有著較好的用途,因此值得掌握。

本文將直接從高度陣列講起,假設讀者具有字尾陣列的基礎知識。首先本文會介紹高度陣列的定義以及用途,接著講解如何在o(n)時間內求出高度陣列,最後將介紹高度陣列的應用。

高度陣列(lcp array ,longest common prefix array)

所謂的字尾陣列,指的是由字尾陣列中相鄰兩個字尾的最長公共字首(lcp)的長度組成的陣列。記字尾陣列為sa,高度陣列為lcp,則有字尾s[ sa[i]… ] 與 s[s[i+1] … ] 的最長公共字首的長度為lcp[i] 。我們可以在o(n)時間內高效地求得高度陣列,有了高度陣列,字尾陣列將稱為乙個更加有力的工具。高度資料雖然計算簡單,但非常巧妙,使用了類似尺取法的技巧。記rank[i] 為位置 i 開始的字尾在字尾陣列中的順序,即有rank[ s[i] ] = i。

構造方法

我們從位置0的字尾開始,從前往後依次計算字尾s[i…]與字尾s[sa[rank[i]-1]…](即字尾陣列中的前乙個字尾)的最長公共字首的長度。此時,假設我們已經求得了位置 i 對應的高度h

ih_i

hi​,那麼我們可以證明位置 i+1 對應的高度應該不小於hi−

1h_i-1

hi​−1。

為什麼呢?記k = sa[rank[i] - 1] ,已知字尾s[i…]和s[k…]的頭部h

ih_i

hi​個字元是相等的,那麼字尾s[i+1…]和s[k+1…]分別是二者去除首字元的結果,所以它們頭部hi−

1h_i-1

hi​−

1個字元是相等的。雖然在字尾陣列中,s[i+1…]前面乙個元素未必就是s[k+1…],但即便如此,公共字首的長度也是只增不減的。因此,只要從hi−

1h_i-1

hi​−

1開始檢查,計算最長公共字首的長度就好了。

**模板

因為高度最多增加n次,所以總的時間複雜度為o(n)。如果把這個問題當作位置i對應的區間是[i,i+h)的尺取法來看,就很容易理解。區間的左右端點始終不會向左移,並且是不超過n的整數。

#include#include#includeusing namespace std;

const int n = 1e6+10;

int n,k;

char str[n];

int sa[n],rank[n],tmp[n],lcp[n];

//比較(rank[i],rank[i+k])和(rank[j],rank[j+k])

bool compare_sa(int i,int j)

//計算字串s的字尾陣列

void construct_sa(char* s,int sa)

//利用對長度為k的排序結果對長度為2k的排序

for(k = 1;k <= n;k *= 2)

}//最長公共字首模板,其中sa為字尾陣列,求得結果存放在lcp

void construct_lcp(char *s,int sa,int lcp)

lcp[rank[i]-1] = h; }}

int main()

return 0;

}

參考資料

最長公共字首

描述 給k個字串,求出他們的最長公共字首 lcp 樣例 在 abcd abef 和 acef 中,lcp 為 a 在 abcdefg abcefg abcefa 中,lcp 為 abc 新知識點 vectorstrs既可以是一維的,也可以是多維的。在這裡講解三維的初始化。vector str str...

最長公共字首

編寫乙個函式來查詢字串陣列中的最長公共字首。如果不存在公共字首,返回空字串 示例 1 輸入 flower flow flight 輸出 fl 示例 2 輸入 dog racecar car 輸出 解釋 輸入不存在公共字首。說明 所有輸入只包含小寫字母a z。class solution object...

最長公共字首

編寫乙個函式來查詢字串陣列中的最長公共字首。如果不存在公共字首,返回空字串 示例 1 輸入 flower flow flight 輸出 fl 示例 2 輸入 dog racecar car 輸出 解釋 輸入不存在公共字首。說明 所有輸入只包含小寫字母a z。param strs return var...