字尾陣列(Suffix Array)

2021-10-04 22:20:19 字數 2977 閱讀 9075

字尾陣列看上去是乙個很高深,很玄妙的東西。

但首先,我們要樹立乙個觀點:它!不難!!

實際上,他也真的不難。難的只是其中乙個想法的操作。除此以外,不難。

首先,我們需要了解一下什麼是字尾

字尾,顧名思義,綴在後面的東西。在字串中,就是綴在字串後面的東西,大家可以聯絡一下英語單詞中的字尾來理解。

舉個例子

字串:abaab

字尾分別有:

abaab, baab, aab, ab, b

相信到這裡,大家已經理解了字尾的概念。那麼接下來,我們來看一下什麼是字尾陣列。

常用的字尾陣列通常有以下幾個陣列變數(字尾陣列的核心):

int sa[maxn]

;int rank[maxn]

;

以下的排序指字串按字典序進行排序。

sa陣列:sa陣列的下標和字串的下標一一對應,sa[0]就表示substr(0, n)排完序之後的次序。

rank陣列:和sa陣列正好相反,rank[i]=j的含義是排名第i的字串在所給字串的位置j處(這裡字串的位置當然是指字串第乙個字元在所給字串中的位置)

總結:sa 和 rank陣列處於一種互補的狀態,可以這麼來區分兩個陣列,sa表示誰第幾名,rank表示第幾名的是誰。

好了,到這,字尾陣列的概念就差不多了。

是不是很簡單??

誒!別急!繼續看下去!

可能很多小夥伴的第一想法就是建立乙個string陣列,把題目給的字串的所有字尾子串存進去。再來乙個sort快排就完事了。

這確實是乙個方法,但是太暴力了。快排的時間複雜度是o(nlogn),但是我們字串大小比較不同於數字的大小比較,字串的大小比較也是乙個o(n)的時間複雜度,這麼一來,這個演算法的時間複雜度就是o(n^2logn),很顯然,這是不可取的!!

這也就是字尾陣列的難點了,怎麼樣對字尾子串進行高效的排序,獲得sa,rank陣列的值。

在這,給大家介紹一種方法,倍增演算法

演算法的大致思想如下:

換一種排序的思路,不是真的對所有的字尾子串進行排序並交換位置(即最開始暴力演算法中的sort)。而是通過一定的規則我們來計算字尾子串的排名。具體思路如下:

第一次排序:對每個字尾子串的前1個字元進行排序

第二次排序:對每個字尾子串的前1—2個字元進行排序

第三次排序:對每個字尾子串的前1—4個字元進行排序

第n次排序:對每個字尾子串的前1—2^(n-1)個字元進行排序

????這啥意思???為什麼這麼做??

上圖!!

其實也有一點點抽象,對著和下面的文字我們來理解一下。

倍增,可以理解為每次比較的字元個數,是按照2的指數增長的(也就是2倍增)。

為什麼採取這種措施?

比方說我們現在要進行第三次排序,也就是對前4個字元進行排序,那麼在此之前的第二次排序,我們一定已對字尾字元的前2個字元進行了排序(再次強調!這裡的排序是「假「的!只是通過比較獲得次序而已)

所以此時,我們可以通過第二次排序的結論來進行第三次排序。

計算任一字尾子串k的前4個字元的次序號z可以通過比較字尾子串k的前2個字元的次序號x和字尾子串k+2的前兩個字元的次序號y,進而得到乙個而元祖(x,y),這是我們後面進行比較排序的資本!

計算任一字尾子串k的前4個字元的次序號z可以通過比較字尾子串k的前2個字元的次序號x和字尾子串k+2的前兩個字元的次序號y,進而得到乙個而元祖(x,y),這是我們後面進行比較排序的資本!

計算任一字尾子串k的前4個字元的次序號z可以通過比較字尾子串k的前2個字元的次序號x和字尾子串k+2的前兩個字元的次序號y,進而得到乙個而元祖(x,y),這是我們後面進行比較排序的資本!

獲得了這個資本之後呢,我們就可以進行排序啦。

比如:

若兩個字尾子串的而元祖分別為(x1, y1) (x2, y2), 排序分別為z1,z2

若 x1**:

#include

#include

#include

using

namespace std;

#define maxn 1000009

string str;

//給定的字串

int n;

//字串的大小

int sa[maxn]

;//所求的字尾陣列

int rank[maxn]

;//表示字尾排第幾的陣列

int tmprank[maxn]

;//臨時儲存rank的值

int k=0;

bool

cmp(

int x,

int y)

//bool

judge

(int str1,

int str2)

//判斷字尾子串x,y的二元組是否相等

return

false;}

void

getsa()

for(k =

1; k <= n; k <<=1)

for(

int i =

1; i <= n; i++

) rank[i]

= tmprank[i];if

(number >= n)

//排序結束,提前退出迴圈

break;}

return;}

intmain()

Suffix Array 字尾陣列

顧名思義,suffixarray 以下有時簡稱sa 和字串的字尾有關。字尾 字串中某個位置一直到結尾的子串。sa中討論包括了原串和空串 所以共有len 1個字尾。字尾陣列 字串的所有字尾組成的按字典序從小到大排好的陣列。由於sa中記錄的都是字串的字尾,所以sa只需要記錄其表示的字尾的起始位置。由於比...

字尾陣列(Suffix Array)

字尾陣列是處理字串的有力工具。sa儲存乙個字串按字典序排列的字尾,如圖 rank陣列儲存字尾i的名次,就是把sa反過來,上圖中 rank 1 2,rank 2 8 height陣列儲存相鄰兩個sa字尾之間公共字首的長度,如圖 思路 用倍增的方法對每個字元開始的長度為2 k2 k 2k子字串進行排序,...

字尾陣列suffix array

倍增演算法,時間複雜度o nlogn sa從小到大儲存相對大小的下標 理解lsd,x陣列,sa陣列 char s maxn int sa maxn t maxn t2 maxn c maxn n void build sa int m void build sa int m int cmp suff...