#include<bits/stdc++.h>
#define ll long long
// Usage:
// SuffixArray sa;
// sa.init(s);
// sa.compute_suffix_array();
// may use sa.getP().
struct SuffixArray {
string s;
int logs;
int len;
int **posi;
int **c;
int alphabet_size;
SuffixArray() {}
void init (string s_) {
s = s_ + "$";
logs = log2(s.size()) + 1;
posi = new int*[logs+1];
c = new int*[logs+1];
for (int i = 0; i <= logs; ++i) {
posi[i] = new int[s.size()];
c[i] = new int[s.size()];
}
len = s.size();
alphabet_size = 256;
}
void compute_suffix_array() {
// first loop
int *cnt = new int[alphabet_size];
fill(cnt, cnt + alphabet_size, 0);
for (int i = 0; i < len; ++i)
cnt[s[i]]++;
for (int i = 1; i < alphabet_size; ++i)
cnt[i] += cnt[i-1];
for (int i = len-1; i >= 0; --i)
posi[0][--cnt[s[i]]] = i;
int classes = 0;
c[0][posi[0][0]] = 0;
for (int i = 1; i < len; ++i)
if (s[posi[0][i]] == s[posi[0][i-1]])
c[0][posi[0][i]] = classes;
else
c[0][posi[0][i]] = ++classes;
classes++;
// second to logs-th loop
int *pn = new int[len];
cnt = new int[len];
for (int h = 0; h < logs; ++h) {
for (int i = 0; i < len; ++i) {
pn[i] = posi[h][i] - (1 << h);
if (pn[i] < 0)
pn[i] += len;
}
fill(cnt, cnt + classes, 0);
for (int i = 0; i < len; i++)
cnt[c[h][pn[i]]]++;
for (int i = 1; i < classes; i++)
cnt[i] += cnt[i-1];
for (int i = len-1; i >= 0; i--) {
posi[h+1][--cnt[c[h][pn[i]]]] = pn[i];
}
c[h+1][posi[h+1][0]] = 0;
classes = 1;
for (int i = 1; i < len; i++) {
pair<int, int> cur = {c[h][posi[h+1][i]], c[h][(posi[h+1][i] + (1 << h)) % len]};
pair<int, int> prev = {c[h][posi[h+1][i-1]], c[h][(posi[h+1][i-1] + (1 << h)) % len]};
if (cur != prev)
++classes;
c[h+1][posi[h+1][i]] = classes - 1;
}
}
// remove the '$' appended at the end of string s
for (int h = 0; h <= logs; ++h) {
for (int i = 0; i <= len - 2; ++i) {
posi[h][i] = posi[h][i+1];
}
}
}
int* getP () {
return posi[logs];
}
};