後綴數組
阿新 • • 發佈:2017-06-12
turn tdi swa -a pen aps 消失 spl one
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 const int MAXN=100001; 7 8 /* s[]: 文本串 9 sa[]: 後綴數組,表示“第i名是誰 ” 10 t[]: 即x[], 表示第一關鍵字下“i是第幾名 ” 11 t2[]: 即y[], 表示第二關鍵字下“第i名是誰 ”,對應sa[] 12 c[]: 桶,用來進行基數排序13 */ 14 15 char s[MAXN]; 16 int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n; 17 18 void build_sa(int m) { //構造後綴數組 19 int i, *x=t, *y=t2; //swap函數參數需為指針 20 //基數排序 21 for (i=1; i<m; i++) c[i]=0; //清桶 22 for (i=0; i<n; i++) c[x[i]=s[i]]++; //x[]=s[]:把k=0時的第一關鍵字排名即字符本身賦給x,c[q]++:入桶23 for (i=1; i<m; i++) c[i]+=c[i-1]; //c[i]~c[i-1]為桶中的數所占的排名,如c[1]=2,c[2]=3執行完該語句變為c[1]=2,c[2]=5表示以1開頭的關鍵字將分配的排名為1,0;以2開頭的分配的排名為4,3,2 24 for (i=n; i>=0; i--) sa[--c[x[i]]]=i;//x[i]"i是第幾名",由於桶的下標按名次來排,所以--c[x[i]]表示分配給i的排名.因為sa表示"第i名是誰",所以sa[i的名次]=i 25 26 for (int k=1; k<=n; k<<=1) { //倍增 27 int p=0; 28 //用sa[]排序第二關鍵字y[],即把第一關鍵字“抄過來” 29 for (i=n-k; i<n; i++) y[p++]=i; //第二關鍵字的前幾名一定是x中最後k位等於0的,直接賦值 30 for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;//把其他排名平移到上一位。因為前K個平移後消失(沒有“上一個關鍵字”所以不被需要),所以不用存;其他的順次平移K位 31 //基數排序第一關鍵字 32 for (i=1; i<m; i++) c[i]=0; 33 for (i=0; i<n; i++) c[x[y[i]]]++; 34 for (i=1; i<m; i++) c[i]+=c[i-1]; 35 for (i=n; i>=0; i--) sa[--c[x[y[i]]]]=y[i]; 36 // 根據sa[]和y[]計算新的x[] 37 swap(x, y); 38 p=1; x[sa[0]]=0; 39 for (i=1; i<n; i++) 40 x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 41 if (p>=n) break; 42 m=p; 43 } 44 return; 45 }
(無註釋版)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; const int MAXN=100001; char s[MAXN]; int sa[MAXN], t[MAXN], t2[MAXN], c[MAXN], n; void build_sa(int m) { int i, *x=t, *y=t2; for (i=1; i<m; i++) c[i]=0; for (i=0; i<n; i++) c[x[i]=s[i]]++; for (i=1; i<m; i++) c[i]+=c[i-1]; for (i=n; i>=0; i--) sa[--c[x[i]]]=i; for (int k=1; k<=n; k<<=1) { int p=0; for (i=n-k; i<n; i++) y[p++]=i; for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (i=1; i<m; i++) c[i]=0; for (i=0; i<n; i++) c[x[y[i]]]++; for (i=1; i<m; i++) c[i]+=c[i-1]; for (i=n; i>=0; i--) sa[--c[x[y[i]]]]=y[i]; swap(x, y); p=1; x[sa[0]]=0; for (i=1; i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if (p>=n) break; m=p; } return; }View Code
後綴數組