字尾陣列詳解

2022-04-30 13:21:14 字數 1931 閱讀 5379

對字串字尾進行快排,\(o(n^2 \ log n)\)

將字串的所有字尾進行雜湊,所有字尾的雜湊值珂以在\(o(n)\)的時間求出

然後就珂以\(o(1)\)比較字串是否相等

這樣,我們就得到了乙個改進演算法:比較兩個字尾時,二分它們的 lcp(最長公共字首) 長度,並比較第一位不同的字元,總時間複雜度為\(o(n \ log^2 n)\)

使用 hash 來構造字尾陣列的好處在於時間複雜度較低,並且珂以動態維護(珂以使用set),壞處在於 hash 的不穩定性。上述兩個演算法,我們都是將兩個字尾看做獨立字串進行比較,而忽視了字尾之間的內在聯絡。乙個更優的演算法是倍增演算法,它的主要思路是,每次利用上一次的結果,倍增計算出從每個位置 \(i\) 開始長度為 \(2^k\) 的子串的排名

如果使用快速排序來實現雙關鍵字排序,總時間複雜度為 \(o(n \ log^2 n)\),實現難度比 hash 的方法要低,並且更穩定。而考慮到每個關鍵字均為 \([−1,n)\) 的整數,我們可以使用 \(o(n)\) 的基數排序,來將總時間複雜度將為 \(o(n \ logn)\)

完整**

#include #define n 1000005

using namespace std;

inline void write(register int x)

char s[n];

int n,m;

int rak[n],tp[n],sa[n],tax[n];

inline void qsort()

inline void suffixsort()

for(register int i=1;i<=n;++i)

write(sa[i]),putchar(' ');

}int main()

常數巨大

①先將字尾分成兩部分,然後對第一部分的字尾排序;

②利用①的結果,對第二部分的字尾排序;

③將①和②的結果合併,即完成對所有字尾排序;

時間複雜度為 \(o(n)\),但常數極大,在較小資料範圍時與倍增演算法相比無明顯優勢,且實現複雜,價效比較低

比倍增法跑的還慢的dc3

#include#define n 1000005

using namespace std;

inline void write(register int x)

char s[n];

int str[n*3],sa[n*3],rank[n],height[n];

int id[n];

inline bool equal(register int *str,register int a,register int b)

inline bool c***(register int *str,register int *nstr,register int a,register int b)

inline void dc3(register int *str,register int *sa,register int n,register int m)

}

rak:從第i個位置開始的字尾的排名

rak珂以根據rak[sa[i]]=i,sa[rak[i]]=i快速求出

有了height陣列後就珂以胡作非為

1.兩個字尾的最大公共字首

lcp(x,y)=min(height[x~y]),用rmq維護,o(1)查詢

2.可重疊最長重複子串

height陣列裡的最大值

3.不可重疊最長重複子串

首先二分答案x,對height陣列進行分組,保證每一組的min_height都》=x

依次列舉每一組,記錄下最大和最小長度,當sa[maxlen]−sa[minlen]>=x那麼可以更新答案

4.本質不同的子串的數量

列舉每乙個字尾,第i個字尾對答案的貢獻為len−sa[i]+1−height[i]

字尾陣列模板詳解。

給定乙個字串s,比如它是 abcad 那麼它的字尾有 abcad bcad cad ad d 講這些字尾字串按照字典序排序,得到的就是字尾陣列。如果用普通的排序方法,排序要o nlogn 但是每兩個字元比較大小要o n 所以是o n n log n 的複雜度。但是利用特殊的演算法可以將其降到o nl...

字尾陣列 倍增法詳解

主要是基於基數排序,如果基數排序沒弄懂 就會很難理解 首先從k 0開始,從字尾陣列裡面選取步長為2 k的字尾陣列的前子串 然後進行基數排序 如果排序後所有的名次陣列的值都不相同,那麼排序結束 否則,k 也就是步長翻倍 繼續排序。陣列sa sorted array 構造完成前表示關鍵字陣列,下標表示名...

字尾陣列倍增演算法模板詳解

2009國家集訓隊 字尾陣列 處理字串的有力工具 羅穗騫 bool cmp int r,int a,int b,int l void init int r,int sa,int n,int m for i 0 i n i rk sa i i int k 0 for i 0 i n 1 h rk i ...