後綴數組(筆記)
阿新 • • 發佈:2019-03-16
lin ++i 小時 ret 類型 cst htm strlen .html
dalao的博客,講的很詳細
倍增法:設當前已知各後綴的前 \(2^k\) 個字符的相對大小關系(即排名數組 \(rank\)), 於是只要用 \((rank[i], rank[i + 2 ^k])\) 進行雙關鍵字排序就可以得到前 \(2^{k+1}\) 個字符的相對大小關系
代碼調了一個小時才知道原來還有指針引用這種玩意
#include<cstdio> #include<cstring> using namespace std; const int MAXN = 1000010; int t1[MAXN], t2[MAXN], sa[MAXN], tax[MAXN]; char str[MAXN]; inline void Swap(int* &a, int* &b){//喪病的復合類型 int *t = a; a = b, b = t; } void getSA(char s[], int len){ int p = 0, crd; int *rak = t1, *tp = t2; crd = 122; for (int i = 1; i <= len; ++i) rak[i] = s[i], tp[i] = i; for (int i = 0; i <= crd; ++i) tax[i] = 0; for (int i = 1; i <= len; ++i) ++tax[rak[i]]; for (int i = 1; i <= crd; ++i) tax[i] += tax[i - 1]; for (int i = len; i >= 1; --i) sa[tax[rak[tp[i]]]--] = tp[i]; for (int w = 1; p != len; w <<= 1, crd = p){ p = 0; for (int i = len - w + 1; i <= len; ++i) tp[++p] = i; for (int i = 1; i <= len; ++i) if (sa[i] > w) tp[++p] = sa[i] - w; for (int i = 0; i <= crd; ++i) tax[i] = 0; for (int i = 1; i <= len; ++i) ++tax[rak[i]]; for (int i = 1; i <= crd; ++i) tax[i] += tax[i - 1]; for (int i = len; i >= 1; --i) sa[tax[rak[tp[i]]]--] = tp[i]; Swap(rak, tp); rak[sa[1]] = p = 1; for (int i = 2; i <= len; ++i) rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p; } } int main(){ scanf("%s", str + 1); int slen = strlen(str + 1); getSA(str, slen); for (int i = 1; i <= slen; ++i) printf("%d ", sa[i]); return 0; }
後綴數組(筆記)