[模板] 后缀数组
int rak[maxn],height[maxn];
void cal_height(vector<int> p,string s){
int n = s.length();
int k = 0;
for(int i = 0;i < n;i++)
rak[p[i]] = i;
for(int i = 0;i < n;i++){
if(k) k--;
int j = p[rak[i] - 1];
while(i + k < n && j + k < n && s[i + k] == s[j + k]) k++;
height[rak[i]] = k;
}
for(int i = 0;i < n;i++)
cout << height[i] << '\n';
}
void count_sort(vector<int> &p,vector<int> &c){
int n = p.size();
vector<int> cnt(n);
for(auto x:c)
cnt[x]++;
vector<int> p_new(n);
vector<int> pos(n);
pos[0] = 0;
for(int i = 1;i < n;i++)
pos[i] = pos[i - 1] + cnt[i - 1];
for(auto x:p){
int i = c[x];
p_new[pos[i]] = x;
pos[i]++;
}
p = p_new;
}
void SA(string s){
s.pb('$');
int n = s.length();
vector<int> p(n),c(n);
{
vector<pair<char,int>> a(n);
for(int i = 0;i < n;i++)
a[i] = make_pair(s[i],i);
sort(a.begin(),a.end());
for(int i = 0;i < n;i++)
p[i] = a[i].se;
c[p[0]] = 0;
for(int i = 1;i < n ;i++){
if(a[i].fi == a[i - 1].fi)
c[p[i]] = c[p[i - 1]];
else
c[p[i]] = c[p[i - 1]] + 1;
}
}
int k = 0;
while((1 << k) < n){
for(int i = 0;i < n;i++)
p[i] = (p[i] - (1 << k) + n) % n;
count_sort(p,c);
vector<int> c_new(n);
c_new[p[0]] = 0;
for(int i = 1;i < n;i++){
pii pre = make_pair(c[p[i - 1]],c[(p[i - 1] + (1 << k)) % n]);
pii now = make_pair(c[p[i]],c[(p[i] + (1 << k)) % n]);
if(now == pre)
c_new[p[i]] = c_new[p[i - 1]];
else
c_new[p[i]] = c_new[p[i - 1]] + 1;
}
c = c_new;
k++;
}
cal_height(p,s);
}
int main(){
string s;
cin >> s;
SA(s);
}