摘要
本文是關於字尾陣列的乙個拓展,問題模型來自於最長公共字首(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...