#include <bits/stdc++.h>
const int MAXN = 1e6 + 10;
using namespace std;
char s[MAXN];
int N, M, rak[MAXN], sa[MAXN], tax[MAXN], tp[MAXN], height[MAXN];

/* sa[i]:排名为i的后缀的位置 rak[i]:从第i个位置开始的后缀的排名,下文为了叙述方便,把从第i个位置开始的后缀简称为后缀i tp[i]:基数排序的第二关键字,意义与sa一样,即第二关键字排名为i的后缀的位置 tax[i]:i号元素出现了多少次。辅助基数排序 s:字符串,s[i]表示字符串中第i个字符串 i号后缀:从i开始的后缀 lcp(x,y):字符串x与字符串y的最长公共前缀,在这里指x号后缀与与y号后缀的最长公共前缀 height[i]:lcp(sa[i],sa[i?1]),即排名为i的后缀与排名为i?1的后缀的最长公共前缀 H[i]:height[rak[i]],即i号后缀与它前一名的后缀的最长公共前缀 性质:H[i]?H[i?1]?1 //两个后缀的最大公共前缀 lcp(x,y)=min(heigh[x?y]), 用rmq维护,O(1)查询 //可重叠最长重复子串 Height数组里的最大值 //不可重叠最长重复子串 首先二分答案x,对height数组进行分组,保证每一组的minheight都>=x 依次枚举每一组,记录下最大和最小长度,多sa[mx]?sa[mi]>=x那么可以更新答案 //本质不同的子串的数量 枚举每一个后缀,第i个后缀对答案的贡献为len?sa[i]+1?height[i] */


void Qsort() {
    for (int i = 0; i <= M; i++) tax[i] = 0;
    for (int i = 1; i <= N; i++) tax[rak[i]]++;
    for (int i = 1; i <= M; i++) tax[i] += tax[i - 1];
    for (int i = N; i >= 1; i--) sa[ tax[rak[tp[i]]]-- ] = tp[i];
}
void SuffixSort() {
    M = 75;
    for (int i = 1; i <= N; i++) rak[i] = s[i] - '0' + 1, tp[i] = i;
    Qsort();
    for (int w = 1, p = 0; p < N; M = p, w <<= 1) {
        p = 0;
        for (int i = 1; i <= w; i++) tp[++p] = N - w + i;
        for (int i = 1; i <= N; i++) if (sa[i] > w) tp[++p] = sa[i] - w;
        Qsort();
        swap(tp, rak);
        rak[sa[1]] = p = 1;
        for (int i = 2; i <= N; i++)
            rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++p;
    }
}

void GetHeight() {
    int k = 0;
    for(int i = 1; i <= N; i++) {
        if(k) k--;
        int j = sa[rak[i] - 1];
        while(s[i + k] == s[j + k]) k++;
        height[rak[i]] = k;
    }
}

int d[MAXN][30];
void RMQ_init(){

    for(int i=1;i<=N;i++){
        d[i][0]=height[i];
    }
    for(int i=1;(1<<i)<=N;i++){
        for(int j=1;(1<<i)+j-1<=N;j++){
            d[j][i]=min(d[j][i-1],d[j+(1<<(i-1))][i-1]);
        }
    }
}

int LCP(int k,int j){
    if(rak[k]>rak[j])
        swap(k,j);
        
    int L=rak[k]+1,R=rak[j];
    int i=0;
    while((1<<(i+1))<=R-L+1)i++;
    return min(d[L][i],d[R-(1<<i)+1][i]);
}


int main() {
    scanf("%s", s + 1);
    N = strlen(s + 1);
    SuffixSort();
    GetHeight();

    for (int i = 1; i <= N; i++)
    {
        printf("%d ", height[i]);
    }

    return 0;
}