Suffix Array 1a145bb6
Suffix array via radix-sort doubling, with the matching O(n) LCP pass woven into the same construction (kactl's SuffixArray). sa[i] is the starting index of the i'th suffix in sorted order; sa.size() == s.size()+1 and sa[0] == s.size() (the appended sentinel, sorts first). lcp[i] = longest common prefix of sa[i] and sa[i-1] (lcp[0] = 0). s must not contain a NUL character. Source: kactl (CC0), see NOTICE.md.
Time: O(n \log n). kactl-derived, tested
content/strings/suffix-array.h
struct SuffixArray {
vector<int> sa, lcp;
SuffixArray(string s, int lim = 256) {
s.push_back(0);
int n = (int)s.size(), k = 0, a, b;
vector<int> x(s.begin(), s.end()), y(n), ws(max(n, lim));
sa = lcp = y;
iota(sa.begin(), sa.end(), 0);
for (int j = 0, p = 0; p < n; j = max((ll)1, j * 2), lim = p) {
p = j;
iota(y.begin(), y.end(), n - j);
rep(i, 0, n) if (sa[i] >= j) y[p++] = sa[i] - j;
fill(ws.begin(), ws.end(), 0);
rep(i, 0, n) ws[x[i]]++;
rep(i, 1, lim) ws[i] += ws[i - 1];
for (int i = n; i--;) sa[--ws[x[y[i]]]] = y[i];
swap(x, y);
p = 1;
x[sa[0]] = 0;
rep(i, 1, n) {
a = sa[i - 1], b = sa[i];
x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++;
}
}
for (int i = 0, j; i < n - 1; lcp[x[i++]] = k)
for (k && k--, j = sa[x[i] - 1]; s[i + k] == s[j + k]; k++);
}
};