字尾陣列,SA

SkyMaths發表於2024-07-30

主要是 \(O(n\log n)\) 倍增求 SA。

(為什麼這麼短)

void SA() {
	int m = 127, p = 0;
	rep(i, 1, n) ++buc[rk[i] = s[i]];
	rep(i, 1, m) buc[i] += buc[i - 1];
	per(i, n, 1) sa[buc[rk[i]]--] = i;

	for(int w = 1; ; m = p, p = 0, w <<= 1) {
		rep(i, n - w + 1, n) id[++p] = i;
		rep(i, 1, n) if(sa[i] > w) id[++p] = sa[i] - w;
		memset(buc, 0, sizeof(buc[0]) * (m + 1));
		rep(i, 1, n) ork[i] = rk[i];
		p = 0;
		rep(i, 1, n) ++buc[rk[i]];
		rep(i, 1, m) buc[i] += buc[i - 1];
		per(i, n, 1) sa[buc[rk[id[i]]]--] = id[i];
		rep(i, 1, n) rk[sa[i]] = (ork[sa[i - 1]] == ork[sa[i]] && ork[sa[i - 1] + w] == ork[sa[i] + w]) ? p : ++p;
		if(p == n) break;
	}
}

相關文章