全文1820詞,預計閱讀時間5min
目錄例題
字尾陣列是處理字串的有力工具,常在比賽中用到。本文主要介紹字尾陣列的概念與部分例題。
關於部分例題,我們將在後續文章介紹。
那麼,我們可以先按第二關鍵字排序,此時序列是按照第二關鍵字從小到大排列的。我們再從左到右,按第一關鍵字排序。這樣就可以使得其有序。這就是基數排序,基數排序是穩定的。
舉個栗子:
(1,6)(1,5)(2,3)(3,4)(8,5)(16,43)(2,20)(4,28)
按第二關鍵字排序後
(2,3)(3,4)(1,5)(8,5)(1,6)(2,20)(4,28)(16,43)
按第一關鍵字排序後
(1,5)(1,6)(2,3)(2,20)(3,4)(4,28)(8,5)(16,43)
此時序列有序
關於字尾陣列的構造,有倍增與\(dc3\)兩種演算法。倍增演算法較為簡單,本文主要介紹倍增演算法。
注:倍增演算法\(o(nlogn)\),\(dc3\)演算法\(o(n)\),\(n\)為字串長度
我們可以對從每個字元開始,長度為\(2^i\)的字串進行排序(當字串長度不足時,根據上文定義,在後面補比所有出現過字元還要小的字元)。當到達\(len_t\le 2^i\),顯然所有字串的排名會變得不重複。並且當長度為\(2^i\)的字串排名不重複時,長度為\(2^\)的字串排名也不重複。
當我們知道長度為\(2^i\)的排名時,如何求出長度為\(2^\)的排名呢?我們知道\(2 \times 2^i=2^\),與上文的基數排序對比,想出怎麼做了嗎?
其實,我們可以直接用\(2^i\)的排名搞。如下圖所示,以前半段的排名為第一關鍵字,以後半段的排名作為第二關鍵字,做基數排序,就可以知道新的排名了。
所以,我們只用在字串中求出長度為\(2^0=1\)的排名,後面的排名都可以通過基數排序求出。
我們的程式基本成形了,步驟如下:
1.求出長度為\(2^0\)的排名
2.基數排序,由\(2^i\)的排名求出\(2^\)的排名
3.處理每個字尾的排名
不過這裡還要介紹乙個優化:第二關鍵字其實不用排序,我們可以通過以下方法得出順序:
設長度為\(2^i\)
1.長度不到\(2^i\)的字串,按從長到短的順序加入陣列
2.從前往後遍歷\(sa\),若\(sa_i-2^i \ge 0\)(字串從0開始),則將其加入陣列
此陣列即為第二關鍵字的排序。
上**(luogu3809)
本題就是求最終的\(sa\)陣列,處理完輸出即可。當然,本題中可以把基數排序換成快排。
#includeusing namespace std;
int rank[1000100],nrank[1000100],sa[1000100],sum[1000100],ans[1000100],n,p[1000100];
string st;
bool the_same(int x,int y,int l)
int main()
-1 (height_ \ge height_}-1\)
證明:
定義\(j\)是開頭為\(sa_-1}\)的字串,其\(lcp\)為\(h_i\)。
那麼以\(j+1\)與\(i\)的\(lcp\)顯然是\(h_i-1\)
由上面的定理,得\(j+1\)至\(i\)中間的\(height\)值大於等於\(h_i-1\)。
顯然,\(rank_i>rank_\),且\(sa_\)在\(j+1\)到\(i-1\)之間。
證畢。所以,\(height_ \ge height_} -1\)
所以,我們可以按照\(rank\)順序,求出\(height\),時間複雜度降為\(o(n)\)
**如下
void calc_height()
{ int j=0;
for (int i=0;iluogu 2408 不同子串個數
(spoj 694 / 705)
題目鏈結 題意:給出乙個字串,求不同子串的個數
題解:乙個子串一定是乙個字尾的字首,所以我們求出子串個數後,再減去相同子串個數,即每個字尾與排名是其前一位的字尾的\(lcp\),即為答案。
詳細題解
例題
學習筆記 字尾陣列 1
目錄 全文1820詞,預計閱讀時間5min 字尾陣列是處理字串的有力工具,常在比賽中用到。本文主要介紹字尾陣列的概念與部分例題。關於部分例題,我們將在後續文章介紹。那麼,我們可以先按第二關鍵字排序,此時序列是按照第二關鍵字從小到大排列的。我們再從左到右,按第一關鍵字排序。這樣就可以使得其有序。這就是...
字尾陣列學習筆記
要用好字尾陣列要先理解裡面幾個陣列的概念 sa i 表示字典序第i大的字尾下標 字典序排名依次是1 len stri ng ra nk i 表示下標為i的字尾字典序排名 he ight i 表示sa i 和sa i 1 最長公共字首的長度.乙個性質 lc p su ffix i suff ix j ...
字尾陣列 學習筆記
字尾陣列是處理字串的強有力的工具 在字串處理當中,字尾樹和字尾陣列都是非常有力的工具。其實字尾陣列是字尾樹的乙個非常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽中字尾陣列比字尾樹要更為實用。我們定義...