QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#631451 | #956. 后缀排序 | maspy | 100 ✓ | 103ms | 24284kb | C++20 | 21.0kb | 2024-10-12 04:09:32 | 2024-10-12 04:09:33 |
Judging History
answer
#line 1 "/home/maspy/compro/library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
// https://codeforces.com/blog/entry/96344
#pragma GCC optimize("Ofast,unroll-loops")
// いまの CF だとこれ入れると動かない?
// #pragma GCC target("avx2,popcnt")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;
template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'010'000'000;
template <>
constexpr ll infty<ll> = 2'020'000'000'000'000'000;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * 2'000'000'000'000'000'000;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...) \
vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)
#define FOR_subset(t, s) for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define stoi stoll
int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_mod_2(int x) { return __builtin_parity(x); }
int popcnt_mod_2(u32 x) { return __builtin_parity(x); }
int popcnt_mod_2(ll x) { return __builtin_parityll(x); }
int popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
template <typename T>
T floor(T a, T b) {
return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
T q = floor(x, y);
return {q, x - q * y};
}
template <typename T, typename U>
T SUM(const vector<U> &A) {
T sm = 0;
for (auto &&a: A) sm += a;
return sm;
}
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()
template <typename T>
T POP(deque<T> &que) {
T a = que.front();
que.pop_front();
return a;
}
template <typename T>
T POP(pq<T> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(pqg<T> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(vc<T> &que) {
T a = que.back();
que.pop_back();
return a;
}
template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
if (check_ok) assert(check(ok));
while (abs(ok - ng) > 1) {
auto x = (ng + ok) / 2;
(check(x) ? ok : ng) = x;
}
return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
FOR(iter) {
double x = (ok + ng) / 2;
(check(x) ? ok : ng) = x;
}
return (ok + ng) / 2;
}
template <class T, class S>
inline bool chmax(T &a, const S &b) {
return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
return (a > b ? a = b, 1 : 0);
}
// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
vc<int> A(S.size());
FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
return A;
}
template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
int N = A.size();
vector<T> B(N + 1);
FOR(i, N) { B[i + 1] = B[i] + A[i]; }
if (off == 0) B.erase(B.begin());
return B;
}
// stable sort
template <typename T>
vector<int> argsort(const vector<T> &A) {
vector<int> ids(len(A));
iota(all(ids), 0);
sort(all(ids), [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
return ids;
}
// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
vc<T> B(len(I));
FOR(i, len(I)) B[i] = A[I[i]];
return B;
}
template <typename T, typename... Vectors>
void concat(vc<T> &first, const Vectors &... others) {
vc<T> &res = first;
(res.insert(res.end(), others.begin(), others.end()), ...);
}
#endif
#line 1 "/home/maspy/compro/library/other/io.hpp"
#define FASTIO
#include <unistd.h>
// https://judge.yosupo.jp/submission/21623
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf
uint32_t pil = 0, pir = 0, por = 0;
struct Pre {
char num[10000][4];
constexpr Pre() : num() {
for (int i = 0; i < 10000; i++) {
int n = i;
for (int j = 3; j >= 0; j--) {
num[i][j] = n % 10 | '0';
n /= 10;
}
}
}
} constexpr pre;
inline void load() {
memcpy(ibuf, ibuf + pil, pir - pil);
pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
pil = 0;
if (pir < SZ) ibuf[pir++] = '\n';
}
inline void flush() {
fwrite(obuf, 1, por, stdout);
por = 0;
}
void rd(char &c) {
do {
if (pil + 1 > pir) load();
c = ibuf[pil++];
} while (isspace(c));
}
void rd(string &x) {
x.clear();
char c;
do {
if (pil + 1 > pir) load();
c = ibuf[pil++];
} while (isspace(c));
do {
x += c;
if (pil == pir) load();
c = ibuf[pil++];
} while (!isspace(c));
}
template <typename T>
void rd_real(T &x) {
string s;
rd(s);
x = stod(s);
}
template <typename T>
void rd_integer(T &x) {
if (pil + 100 > pir) load();
char c;
do
c = ibuf[pil++];
while (c < '-');
bool minus = 0;
if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
if (c == '-') { minus = 1, c = ibuf[pil++]; }
}
x = 0;
while ('0' <= c) { x = x * 10 + (c & 15), c = ibuf[pil++]; }
if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
if (minus) x = -x;
}
}
void rd(int &x) { rd_integer(x); }
void rd(ll &x) { rd_integer(x); }
void rd(i128 &x) { rd_integer(x); }
void rd(u32 &x) { rd_integer(x); }
void rd(u64 &x) { rd_integer(x); }
void rd(u128 &x) { rd_integer(x); }
void rd(double &x) { rd_real(x); }
void rd(long double &x) { rd_real(x); }
void rd(f128 &x) { rd_real(x); }
template <class T, class U>
void rd(pair<T, U> &p) {
return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T>
void rd_tuple(T &t) {
if constexpr (N < std::tuple_size<T>::value) {
auto &x = std::get<N>(t);
rd(x);
rd_tuple<N + 1>(t);
}
}
template <class... T>
void rd(tuple<T...> &tpl) {
rd_tuple(tpl);
}
template <size_t N = 0, typename T>
void rd(array<T, N> &x) {
for (auto &d: x) rd(d);
}
template <class T>
void rd(vc<T> &x) {
for (auto &d: x) rd(d);
}
void read() {}
template <class H, class... T>
void read(H &h, T &... t) {
rd(h), read(t...);
}
void wt(const char c) {
if (por == SZ) flush();
obuf[por++] = c;
}
void wt(const string s) {
for (char c: s) wt(c);
}
void wt(const char *s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) wt(s[i]);
}
template <typename T>
void wt_integer(T x) {
if (por > SZ - 100) flush();
if (x < 0) { obuf[por++] = '-', x = -x; }
int outi;
for (outi = 96; x >= 10000; outi -= 4) {
memcpy(out + outi, pre.num[x % 10000], 4);
x /= 10000;
}
if (x >= 1000) {
memcpy(obuf + por, pre.num[x], 4);
por += 4;
} else if (x >= 100) {
memcpy(obuf + por, pre.num[x] + 1, 3);
por += 3;
} else if (x >= 10) {
int q = (x * 103) >> 10;
obuf[por] = q | '0';
obuf[por + 1] = (x - q * 10) | '0';
por += 2;
} else
obuf[por++] = x | '0';
memcpy(obuf + por, out + outi + 4, 96 - outi);
por += 96 - outi;
}
template <typename T>
void wt_real(T x) {
ostringstream oss;
oss << fixed << setprecision(15) << double(x);
string s = oss.str();
wt(s);
}
void wt(int x) { wt_integer(x); }
void wt(ll x) { wt_integer(x); }
void wt(i128 x) { wt_integer(x); }
void wt(u32 x) { wt_integer(x); }
void wt(u64 x) { wt_integer(x); }
void wt(u128 x) { wt_integer(x); }
void wt(double x) { wt_real(x); }
void wt(long double x) { wt_real(x); }
void wt(f128 x) { wt_real(x); }
template <class T, class U>
void wt(const pair<T, U> val) {
wt(val.first);
wt(' ');
wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
if constexpr (N < std::tuple_size<T>::value) {
if constexpr (N > 0) { wt(' '); }
const auto x = std::get<N>(t);
wt(x);
wt_tuple<N + 1>(t);
}
}
template <class... T>
void wt(tuple<T...> tpl) {
wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) wt(' ');
wt(val[i]);
}
}
template <class T>
void wt(const vector<T> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) wt(' ');
wt(val[i]);
}
}
void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
wt(head);
if (sizeof...(Tail)) wt(' ');
print(forward<Tail>(tail)...);
}
// gcc expansion. called automaticall after main.
void __attribute__((destructor)) _d() { flush(); }
} // namespace fastio
using fastio::read;
using fastio::print;
using fastio::flush;
#if defined(LOCAL)
#define SHOW(...) SHOW_IMPL(__VA_ARGS__, SHOW6, SHOW5, SHOW4, SHOW3, SHOW2, SHOW1)(__VA_ARGS__)
#define SHOW_IMPL(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define SHOW1(x) print(#x, "=", (x)), flush()
#define SHOW2(x, y) print(#x, "=", (x), #y, "=", (y)), flush()
#define SHOW3(x, y, z) print(#x, "=", (x), #y, "=", (y), #z, "=", (z)), flush()
#define SHOW4(x, y, z, w) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w)), flush()
#define SHOW5(x, y, z, w, v) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", (v)), flush()
#define SHOW6(x, y, z, w, v, u) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", (v), #u, "=", (u)), flush()
#else
#define SHOW(...)
#endif
#define INT(...) \
int __VA_ARGS__; \
read(__VA_ARGS__)
#define LL(...) \
ll __VA_ARGS__; \
read(__VA_ARGS__)
#define U32(...) \
u32 __VA_ARGS__; \
read(__VA_ARGS__)
#define U64(...) \
u64 __VA_ARGS__; \
read(__VA_ARGS__)
#define STR(...) \
string __VA_ARGS__; \
read(__VA_ARGS__)
#define CHAR(...) \
char __VA_ARGS__; \
read(__VA_ARGS__)
#define DBL(...) \
double __VA_ARGS__; \
read(__VA_ARGS__)
#define VEC(type, name, size) \
vector<type> name(size); \
read(name)
#define VV(type, name, h, w) \
vector<vector<type>> name(h, vector<type>(w)); \
read(name)
void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 3 "main.cpp"
#line 2 "/home/maspy/compro/library/string/suffix_array.hpp"
#line 2 "/home/maspy/compro/library/alg/monoid/min.hpp"
template <typename E>
struct Monoid_Min {
using X = E;
using value_type = X;
static constexpr X op(const X &x, const X &y) noexcept { return min(x, y); }
static constexpr X unit() { return infty<E>; }
static constexpr bool commute = true;
};
#line 2 "/home/maspy/compro/library/ds/sparse_table/sparse_table.hpp"
// 冪等なモノイドであることを仮定。disjoint sparse table より x 倍高速
template <class Monoid>
struct Sparse_Table {
using MX = Monoid;
using X = typename MX::value_type;
int n, log;
vvc<X> dat;
Sparse_Table() {}
Sparse_Table(int n) { build(n); }
template <typename F>
Sparse_Table(int n, F f) {
build(n, f);
}
Sparse_Table(const vc<X>& v) { build(v); }
void build(int m) {
build(m, [](int i) -> X { return MX::unit(); });
}
void build(const vc<X>& v) {
build(len(v), [&](int i) -> X { return v[i]; });
}
template <typename F>
void build(int m, F f) {
n = m, log = 1;
while ((1 << log) < n) ++log;
dat.resize(log);
dat[0].resize(n);
FOR(i, n) dat[0][i] = f(i);
FOR(i, log - 1) {
dat[i + 1].resize(len(dat[i]) - (1 << i));
FOR(j, len(dat[i]) - (1 << i)) {
dat[i + 1][j] = MX::op(dat[i][j], dat[i][j + (1 << i)]);
}
}
}
X prod(int L, int R) {
if (L == R) return MX::unit();
if (R == L + 1) return dat[0][L];
int k = topbit(R - L - 1);
return MX::op(dat[k][L], dat[k][R - (1 << k)]);
}
template <class F>
int max_right(const F check, int L) {
assert(0 <= L && L <= n && check(MX::unit()));
if (L == n) return n;
int ok = L, ng = n + 1;
while (ok + 1 < ng) {
int k = (ok + ng) / 2;
bool bl = check(prod(L, k));
if (bl) ok = k;
if (!bl) ng = k;
}
return ok;
}
template <class F>
int min_left(const F check, int R) {
assert(0 <= R && R <= n && check(MX::unit()));
if (R == 0) return 0;
int ok = R, ng = -1;
while (ng + 1 < ok) {
int k = (ok + ng) / 2;
bool bl = check(prod(k, R));
if (bl) ok = k;
if (!bl) ng = k;
}
return ok;
}
};
#line 5 "/home/maspy/compro/library/string/suffix_array.hpp"
// 辞書順 i 番目の suffix が j 文字目始まりであるとき、
// SA[i] = j, ISA[j] = i
// |S|>0 を前提(そうでない場合 dummy 文字を追加して利用せよ)
struct Suffix_Array {
vc<int> SA;
vc<int> ISA;
vc<int> LCP;
Sparse_Table<Monoid_Min<int>> seg;
bool build_seg;
Suffix_Array(string& s) {
build_seg = 0;
assert(len(s) > 0);
char first = 127, last = 0;
for (auto&& c: s) {
chmin(first, c);
chmax(last, c);
}
SA = calc_suffix_array(s, first, last);
calc_LCP(s);
}
Suffix_Array(vc<int>& s) {
build_seg = 0;
assert(len(s) > 0);
SA = calc_suffix_array(s);
calc_LCP(s);
}
// lcp(S[i:], S[j:])
int lcp(int i, int j) {
if (!build_seg) {
build_seg = true;
seg.build(LCP);
}
int n = len(SA);
if (i == n || j == n) return 0;
if (i == j) return n - i;
i = ISA[i], j = ISA[j];
if (i > j) swap(i, j);
return seg.prod(i, j);
}
// S[i:] との lcp が n 以上であるような半開区間
pair<int, int> lcp_range(int i, int n) {
if (!build_seg) {
build_seg = true;
seg.build(LCP);
}
i = ISA[i];
int a = seg.min_left([&](auto e) -> bool { return e >= n; }, i);
int b = seg.max_right([&](auto e) -> bool { return e >= n; }, i);
return {a, b + 1};
}
// -1: S[L1:R1) < S[L2, R2)
// 0: S[L1:R1) = S[L2, R2)
// +1: S[L1:R1) > S[L2, R2)
int compare(int L1, int R1, int L2, int R2) {
int n1 = R1 - L1, n2 = R2 - L2;
int n = lcp(L1, L2);
if (n == n1 && n == n2) return 0;
if (n == n1) return -1;
if (n == n2) return 1;
return (ISA[L1 + n] > ISA[L2 + n] ? 1 : -1);
}
private:
void induced_sort(const vc<int>& vect, int val_range, vc<int>& SA,
const vc<bool>& sl, const vc<int>& lms_idx) {
vc<int> l(val_range, 0), r(val_range, 0);
for (int c: vect) {
if (c + 1 < val_range) ++l[c + 1];
++r[c];
}
partial_sum(l.begin(), l.end(), l.begin());
partial_sum(r.begin(), r.end(), r.begin());
fill(SA.begin(), SA.end(), -1);
for (int i = (int)lms_idx.size() - 1; i >= 0; --i)
SA[--r[vect[lms_idx[i]]]] = lms_idx[i];
for (int i: SA)
if (i >= 1 && sl[i - 1]) SA[l[vect[i - 1]]++] = i - 1;
fill(r.begin(), r.end(), 0);
for (int c: vect) ++r[c];
partial_sum(r.begin(), r.end(), r.begin());
for (int k = (int)SA.size() - 1, i = SA[k]; k >= 1; --k, i = SA[k])
if (i >= 1 && !sl[i - 1]) { SA[--r[vect[i - 1]]] = i - 1; }
}
vc<int> SA_IS(const vc<int>& vect, int val_range) {
const int n = vect.size();
vc<int> SA(n), lms_idx;
vc<bool> sl(n);
sl[n - 1] = false;
for (int i = n - 2; i >= 0; --i) {
sl[i] = (vect[i] > vect[i + 1] || (vect[i] == vect[i + 1] && sl[i + 1]));
if (sl[i] && !sl[i + 1]) lms_idx.push_back(i + 1);
}
reverse(lms_idx.begin(), lms_idx.end());
induced_sort(vect, val_range, SA, sl, lms_idx);
vc<int> new_lms_idx(lms_idx.size()), lms_vec(lms_idx.size());
for (int i = 0, k = 0; i < n; ++i)
if (!sl[SA[i]] && SA[i] >= 1 && sl[SA[i] - 1]) {
new_lms_idx[k++] = SA[i];
}
int cur = 0;
SA[n - 1] = cur;
for (size_t k = 1; k < new_lms_idx.size(); ++k) {
int i = new_lms_idx[k - 1], j = new_lms_idx[k];
if (vect[i] != vect[j]) {
SA[j] = ++cur;
continue;
}
bool flag = false;
for (int a = i + 1, b = j + 1;; ++a, ++b) {
if (vect[a] != vect[b]) {
flag = true;
break;
}
if ((!sl[a] && sl[a - 1]) || (!sl[b] && sl[b - 1])) {
flag = !((!sl[a] && sl[a - 1]) && (!sl[b] && sl[b - 1]));
break;
}
}
SA[j] = (flag ? ++cur : cur);
}
for (size_t i = 0; i < lms_idx.size(); ++i) lms_vec[i] = SA[lms_idx[i]];
if (cur + 1 < (int)lms_idx.size()) {
auto lms_SA = SA_IS(lms_vec, cur + 1);
for (size_t i = 0; i < lms_idx.size(); ++i) {
new_lms_idx[i] = lms_idx[lms_SA[i]];
}
}
induced_sort(vect, val_range, SA, sl, new_lms_idx);
return SA;
}
vc<int> calc_suffix_array(const string& s, const char first = 'a',
const char last = 'z') {
vc<int> vect(s.size() + 1);
copy(begin(s), end(s), begin(vect));
for (auto& x: vect) x -= (int)first - 1;
vect.back() = 0;
auto ret = SA_IS(vect, (int)last - (int)first + 2);
ret.erase(ret.begin());
return ret;
}
vc<int> calc_suffix_array(const vc<int>& s) {
vc<int> ss = s;
UNIQUE(ss);
vc<int> vect(s.size() + 1);
copy(all(s), vect.begin());
for (auto& x: vect) x = LB(ss, x) + 1;
vect.back() = 0;
auto ret = SA_IS(vect, MAX(vect) + 2);
ret.erase(ret.begin());
return ret;
}
template <typename STRING>
void calc_LCP(const STRING& s) {
int n = s.size(), k = 0;
ISA.resize(n);
LCP.resize(n);
for (int i = 0; i < n; i++) ISA[SA[i]] = i;
for (int i = 0; i < n; i++, k ? k-- : 0) {
if (ISA[i] == n - 1) {
k = 0;
continue;
}
int j = SA[ISA[i] + 1];
while (i + k < n && j + k < n && s[i + k] == s[j + k]) k++;
LCP[ISA[i]] = k;
}
LCP.resize(n - 1);
}
};
#line 5 "main.cpp"
void solve() {
STR(S);
Suffix_Array X(S);
auto SA = X.SA;
for (auto& x: SA) ++x;
print(SA);
}
signed main() { solve(); }
Details
Tip: Click on the bar to expand more detailed information
Pretests
Final Tests
Test #1:
score: 10
Accepted
time: 1ms
memory: 3696kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T
output:
67 61 68 62 99 87 44 70 69 32 36 3 5 77 94 11 96 89 8 56 17 54 88 63 41 13 1 33 83 74 37 45 21 57 80 22 64 58 18 29 71 75 42 47 92 66 38 76 95 15 81 52 16 98 4 12 10 19 23 85 14 6 2 27 35 100 26 39 91 78 24 46 55 30 34 65 72 43 20 82 48 40 28 84 25 31 93 97 86 53 51 90 49 73 9 59 50 60 7 79
result:
ok 100 numbers
Test #2:
score: 10
Accepted
time: 1ms
memory: 3728kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
67 834 61 984 435 230 932 390 302 791 991 68 961 835 551 887 814 423 143 749 541 62 166 729 910 465 764 663 382 361 252 193 481 996 99 366 668 700 265 321 985 246 843 804 737 807 854 851 436 813 239 231 543 927 848 680 139 767 744 317 87 560 724 44 775 783 800 718 70 172 657 445 240 401 499 756 794 ...
result:
ok 1000 numbers
Test #3:
score: 10
Accepted
time: 1ms
memory: 3980kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
67 834 61 984 435 230 932 390 302 791 991 68 961 835 551 887 814 423 143 749 541 62 166 729 910 465 764 663 382 361 252 193 481 996 99 366 668 700 265 321 985 246 843 804 737 807 854 851 436 813 239 231 543 927 848 680 139 767 744 317 87 560 724 44 775 783 800 718 70 172 657 445 240 401 499 756 794 ...
result:
ok 1000 numbers
Test #4:
score: 10
Accepted
time: 1ms
memory: 3960kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
1215 67 7665 834 1826 7511 5919 3053 61 3312 6300 2679 1594 4074 9549 3994 1216 9041 7309 984 435 9744 230 1246 7870 2136 1083 932 390 3023 6221 2107 5961 302 791 991 3530 3946 4059 9751 2781 68 5494 7719 5334 7001 8839 3525 2856 2330 4033 1358 7135 8275 7042 2156 1353 5431 1327 8878 1858 7963 6070 ...
result:
ok 10000 numbers
Test #5:
score: 10
Accepted
time: 0ms
memory: 3960kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
1215 67 7665 834 1826 7511 5919 3053 61 3312 6300 2679 1594 4074 9549 3994 1216 9041 7309 984 435 9744 230 1246 7870 2136 1083 932 390 3023 6221 2107 5961 302 791 991 3530 3946 4059 9751 2781 68 5494 7719 5334 7001 8839 3525 2856 2330 4033 1358 7135 8275 7042 2156 1353 5431 1327 8878 1858 7963 6070 ...
result:
ok 10000 numbers
Test #6:
score: 10
Accepted
time: 10ms
memory: 5532kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
68971 23766 16236 84001 1215 26527 48751 32248 30140 72030 28767 92557 43162 24259 25407 54376 75855 19511 13517 67 53747 87651 14066 82459 71782 86029 43950 97897 47837 7665 68972 13510 834 32328 99196 78406 83547 81136 78839 87297 70893 11242 63345 90340 71195 48534 1826 26208 37790 94754 94139 42...
result:
ok 100000 numbers
Test #7:
score: 10
Accepted
time: 4ms
memory: 5460kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
68971 23766 16236 84001 1215 26527 48751 32248 30140 72030 28767 92557 43162 24259 25407 54376 75855 19511 13517 67 53747 87651 14066 82459 71782 86029 43950 97897 47837 7665 68972 13510 834 32328 99196 78406 83547 81136 78839 87297 70893 11242 63345 90340 71195 48534 1826 26208 37790 94754 94139 42...
result:
ok 100000 numbers
Test #8:
score: 10
Accepted
time: 103ms
memory: 24248kb
input:
5Q2K2Pz3vL3K5NFJ48Lj77MYpTRo8dq25fS26BUl59i16a9kuxuFu4d477vz0057gB00218hv69C2Wz7Fk5pMt153uVAq3F3rK0T6x537w3ME8JK5N1K1H2mQ25fhwSXF71PN7pq33144n03i7668I924792U1O299jyC066396197Az5XUG4436L1gj5ltv0K591DJu2Fb8UGV54Uz7B1E37583565h6XKWb011m429JT119a5Aa0nGP880GI7691f8bs920iq4725A9W7VYVLJrM7Y3KHhdO6562B34gqZ...
output:
702437 852879 412799 162791 928297 702438 622989 983054 642549 261095 377477 552453 679737 416887 68971 278337 315744 160869 995837 186829 681266 327995 277671 818964 351970 838627 883654 348201 749182 652099 725131 290366 677064 877296 529774 170877 594821 447484 471517 964025 208565 255655 507795 ...
result:
ok 1000000 numbers
Test #9:
score: 10
Accepted
time: 92ms
memory: 24260kb
input:
eX8N69cLH4G7P8QDy5156Hx8m0VN4sH9t0C4MoGd0cN51dgGXJL73z6N20CLISd0X1nhFKvdXa5q2nWCMjmkM30Es5tAZ5L6c306nT2oQfrf2Zt510ofV35o9TJ5T811LtWMrZyh18MX9qw72109C5be766Bd3qLO4xD1DDe479eUE5987M7D8Y895fT1W8v76E093n631511T0UVJh29806570CW9b5Is483605N8654a5VWS08UxTJE91bpt43f74q0hkMd1Z9a23he6MAE3kG0u5127tc3h5f8y39AjD9...
output:
38596 639028 437546 648133 351969 176869 229309 186806 709078 462998 756773 229120 449395 203997 694956 387238 859598 730372 206962 594419 304109 865880 486633 87868 144959 580819 713317 427972 274476 938366 686801 782959 62962 785003 847579 57996 600405 148706 255431 125253 470979 965679 925624 274...
result:
ok 1000000 numbers
Test #10:
score: 10
Accepted
time: 98ms
memory: 24284kb
input:
8585jh1f9l3466C87O58gfT7sPR0Vw2kdl75l450z1aiD294Q98lb2h4eWb77E8O987OzoJ1617c76ewlDF6G35z0p51g7X53r9642d72kX96JaJra72G832G87vyY42UVx980GB137H85hg47CMn3o1249D6aaGPCr8z3f0pptL20TH1X6ec0vg1zJ22kw3DF96bCo708qr75G8n59J3v7m2164IX1N84D8O10byi86jR44lQ7U9ccl490428AkdTY6830E7VVf5705W86IJ0MvY94653hx18on20J44890...
output:
73767 216802 73768 690419 604466 827813 587942 736629 238255 331491 654128 797636 599436 533392 476737 533131 558055 861637 813759 428079 371878 574078 216803 151038 556486 238788 165007 289648 324429 383245 331977 951071 341486 342866 674032 50992 680691 104594 382352 956720 401592 251525 523118 51...
result:
ok 1000000 numbers