const int Maxn = 2 * 1e5;
const int Inf = 0x3f3f3f3f;
int sa[Maxn + 5], id_bak[Maxn + 5];
int sort_id[Maxn + 5], poi_bak[Maxn + 5];
int tem[Maxn * 2 + 5];
void Init_Bak (int n, int m) {
rep (i, 1, m)
poi_bak[i] = 0;
rep (i, 1, n)
poi_bak[id_bak[i]]++;
rep (i, 1, m)
poi_bak[i] += poi_bak[i - 1];
}
void Sort_L (int n) {
per (i, n, 1)
sa[poi_bak[id_bak[sort_id[i]]]--] = sort_id[i];
}
void Get_Sa (int n, int m, char *str) {
rep (i, 1, n) {
id_bak[i] = str[i];
sort_id[i] = i;
}
Init_Bak (n, m);
Sort_L (n);
for (int len = 1; len < n; len <<= 1) {
Init_Bak (n, m);
int Now_Rank = 0;
rep (i, n - len + 1, n) {
sort_id[++Now_Rank] = i;
}
rep (i, 1, n)
if (sa[i] > len)
sort_id[++Now_Rank] = sa[i] - len;
Sort_L (n);
rep (i, 1, n) tem[i] = id_bak[i];
Now_Rank = 1; id_bak[sa[1]] = 1;
rep (i, 2, n) {
if (tem[sa[i - 1]] != tem[sa[i]] || tem[sa[i - 1] + len] != tem[sa[i] + len])
Now_Rank++;
id_bak[sa[i]] = Now_Rank;
}
m = Now_Rank;
}
}
int H[Maxn + 5], Height[Maxn + 5];
void Get_Height (int n, char *str) {
rep (i, 1, n) {
H[i] = Max (H[i - 1] - 1, 0);
if (id_bak[i] == 1) continue;
while (str[i + H[i]] == str[sa[id_bak[i] - 1] + H[i]]) {
H[i]++;
}
}
rep (i, 1, n) {
Height[i] = H[sa[i]];
}
}