Suffix Array
This content is not available in your language yet.
namespace Algorithm { template<typename T> std::vector<int32_t> sort_cyclic_shifts(std::span<T> const& s) { int32_t n = static_cast<int32_t>(s.size()); int32_t class_idx = std::ranges::max(s); std::vector<int32_t> p(n), q(n), c(s.begin(), s.end()), cnt(std::max(class_idx + 1, n)); std::iota(p.begin(), p.end(), 0);
auto counting_sort = [&]() { std::fill_n(cnt.begin(), class_idx + 1, 0); for (auto i : std::views::iota(0, n)) ++cnt[c[p[i]]]; for (auto i : std::views::iota(1, class_idx + 1)) cnt[i] += cnt[i - 1]; for (auto i : std::views::iota(0, n) | std::views::reverse) q[--cnt[c[p[i]]]] = p[i]; p.swap(q); };
auto assign_classes = [&](int32_t const& k) { q[p[0]] = class_idx = 0; for (int i = 1; i < n; ++i) { std::tuple<int, int> cur = {c[p[i ]], c[(p[i ] + k) % n]}; std::tuple<int, int> prev = {c[p[i - 1]], c[(p[i - 1] + k) % n]}; if (cur != prev) ++class_idx; q[p[i]] = class_idx; } c.swap(q); };
counting_sort(); assign_classes(0); for (int32_t k = 1; k < n; k <<= 1) { for (auto& x : p) { x -= k; if (x < 0) x += n; } counting_sort(); assign_classes(k); } return p; }}
namespace String { std::vector<int> suffix_array(std::string& s) { s.push_back('$'); auto suffix_array = Algorithm::sort_cyclic_shifts<char const>({s.begin(), s.length()}); s.pop_back(); suffix_array.erase(suffix_array.begin()); return suffix_array; }}
int main() { std::string s; std::cin >> s; auto suffix_array_of_s = String::suffix_array(s); for (auto const& x : suffix_array_of_s) std::cout << x << ' ';}
abaab
2 3 0 4 1