1. 程式人生 > >後綴數組代碼詳解

後綴數組代碼詳解

技術 決定 getheight break 所在 離散 兩個 tps wid

說起來學了很久的後綴數組了

思想還是很容易明白的

最大的問題就是

代碼看不懂

技術分享圖片

然後在不斷模擬研究的過程中

終於弄清楚了一點

就決定寫下來了

不然又會忘的QAQ

以下是代碼

ps:首先要弄懂基數排序

定義:c[ ]數組 : 基數排序的桶

x[ ]數組:類似於rank數組,保存當前排序到的以每個位置開始的一段字符串的排名

sa[ ]數組:sa[i]保存第i個排名的字符串開頭所在位置

y[ ]數組:第二關鍵字排序,y[i]保存第i個排名的字符串開頭所在位置

 1  void BuildSa(int m) { 
 2       int
*x = t, *y = t2; //這是對單個字符的排序 3 for (int i = 0; i < m; i++) c[i] = 0; // 清空c數組 4 for (int i = 0; i < n; i++) c[x[i] = s[i]]++; // 初始長度為1時, x[i] == s[i] 5 for (int i = 1; i < m; i++) c[i] += c[i - 1]; // 得到每個所在位置 6 for (int i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i; //
排名為c[x[i]]的字符,是從i位置開始的,每記錄一次排名就-1,到前一個位置,保證排名和對應位置不重復 7 for (int k = 1; k <= n; k <<= 1) { 8   int p = 0; // 計數用的 9   for (int i = n - k; i < n; i++) y[p++] = i; // 0是最小的,先把後面需要補0的放在最前面 10   for (int i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k; //
sa[i] < k時不是第二關鍵字, sa[i]的排名是依次遞增的,所以直接讀入y數組,減去前面不是第二關鍵字的部分 11   for (int i = 0; i < m; i++) c[i] = 0; // 清空c數組 12   for (int i = 0; i < n; i++) c[x[y[i]]]++; // 此時在y中已經按第二關鍵字排好序,x中存的是第一關鍵字,再直接基數排序第一關鍵字即可 13 for (int i = 1; i < m; i++) c[i] += c[i - 1]; 14 for (int i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; 15 swap(x, y); 16 // 離散化排名 17 p = 1; x[sa[0]] = 0; 18 for (int i = 1; i < n; i++) 19   x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; // 兩個關鍵字都相同則排名相同 20 if (p >= n) break; // p代表了不同排名數量,若數量已經達到n,則排序完畢,可直接退出 21 m = p; 22 } 23 }

這是得到sa數組的做法

然而

一個sa數組並沒有什麽用

下面是得到height數組的算法

具體證明可以參考

https://wenku.baidu.com/view/ed1be61e10a6f524ccbf85fd.html

這個論文

寫的很好啦

就是沒有註釋...

首先還是上代碼

定義:rank[ ]數組:與sa[ ]數組正好相反,rank[i] = j代表以i開始的後綴的排名

 1 void GetHeight() {
 2     int k = 0;
 3     for (int i = 0; i < n; i++)    rank[sa[i]] = i; 
 4     for (int i = 0; i < n; i++)    {
 5         if (k)    k--; // 因為h[i] >= h[i - 1] - 1(h[i]看論文的定義),所以k需要-1 
 6         int j = sa[rank[i] - 1]; //得到排名前一位後綴開始位置
 7         while (s[i + k] == s[j + k])    k++; //從後面k個開始比較,直到不相同為止
 8         height[rank[i]] = k;
 9     }
10 }

後綴數組代碼詳解