// 后缀数组 学习笔记 boolcmp(int x, int y, int w){ return trk[x] == trk[y] && trk[x + w] == trk[y + w]; }
voidSA(int n){ // 计数排序数组,cnt 为当前值所对应的个数, id 为按照第二关键字排号的序列。 staticint cnt[Maxn], id[Maxn]; int m = 300, p; // 对字符的排序 for (int i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]]; for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1]; for (int i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i; for (int w = 1; ; w <<= 1, m = p) { // 将第二关键字排序(已优化) p = 0; for (int i = n; i > n - w; --i) id[++p] = i; for (int k = 1; k <= n; ++k) if (sa[k] > w) id[++p] = sa[k] - w; // 第一关键字排序 memset (cnt, 0, sizeof (cnt)); for (int i = 1; i <= n; ++i) ++cnt[rk[id[i]]]; for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1]; for (int i = n; i >= 1; --i) sa[cnt[rk[id[i]]]--] = id[i]; // 处理求 RK 数组,处理值域。 memcpy (trk, rk, sizeof (rk)); p = 0; for (int i = 1; i <= n; ++i) rk[sa[i]] = cmp (sa[i], sa[i - 1], w) ? p : ++p; // 收尾 if (p == n) { for (int i = 1; i <= n; ++i) sa[rk[i]] = i; break; } } for (int i = 1, k = 0; i <= n; ++i) { if (k) --k; while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k; h[rk[i]] = k; } }