#include <bits/stdc++.h>
using namespace std;
const int last = 1e8 + 9;
struct node{
int st, ed;
node* child[256];
node* suffixLink;
node(int l, int r) : st(l), ed(r){
for(int j = 0; j < 256; j++)
child[j] = NULL;
suffixLink = NULL;
}
};
node *roots, *activeNode, *curr;
int activeLength = 0, activeEdge = -1, remains = 0;
string s;
char getNext(int x){
curr = activeNode -> child[s[activeEdge]];
int pos = curr -> st + activeLength;
int ends_at = (curr -> ed == last)? x : curr -> ed;
if(pos <= ends_at) return s[pos];
if(pos == ends_at + 1){
if(curr -> child[s[x]]) return s[x];
return s[pos];
}
activeLength -= (ends_at - curr -> st + 1);
activeNode = curr;
activeEdge = activeEdge + (ends_at - curr -> st + 1);
return getNext(x);
}
bool walkdown(int x){
if(activeLength == 0) return false;
curr = activeNode -> child[s[activeEdge]];
int ends_at = (curr -> ed == last)? x : curr -> ed;
//cout << pos << " " << ends_at << endl;
if(ends_at - curr -> st < activeLength){
activeNode = curr;
activeLength -= (ends_at - curr -> st);
activeEdge = curr -> child[s[x]] -> st;
}
else activeLength ++;
}
void startPhase(int j){
//cout << j << " " << remains << endl << endl;
node* lastNewNode = NULL;
remains ++;
while(remains > 0){
//cout << remains << endl;
if(activeLength == 0){
if(roots -> child[s[j]]){
activeNode = roots;
activeEdge = roots->child[s[j]]->st;
activeLength = 1;
//cout << "here!" << endl;
break;
}
else{
roots -> child[s[j]] = new node(j, last);
remains --;
continue;
}
}
else{
curr = activeNode -> child[s[activeEdge]];
//cout << " [" << curr -> st << " " << curr -> ed << "]\n";
char ch = getNext(j);
if(ch == s[j]){
//activeLength++;
walkdown(j);
if(lastNewNode != NULL)
lastNewNode ->suffixLink = activeNode;
break;
}
else{
curr = activeNode -> child[s[activeEdge]];
int pos = curr -> st + (activeLength );
int ends_at = (curr -> ed == last)? j : curr -> ed;
if(pos <= ends_at){
node* interalNode = new node(curr -> st, pos-1);
node* leaf = new node(j, last);
curr -> st = pos;
interalNode -> child[s[j]] = leaf;
interalNode -> child[s[pos]] = curr;
activeNode -> child[s[interalNode -> st]] = interalNode;
if(lastNewNode != NULL){
lastNewNode->suffixLink = interalNode;
//cout << "here" << endl;
}
lastNewNode = interalNode;
interalNode -> suffixLink = roots;
}
else{
curr -> child[s[j]] = new node(j, last);
//curr -> suffixLink = roots;
if(lastNewNode != NULL)
lastNewNode->suffixLink = curr;
lastNewNode = curr;
}
remains --;
if(activeNode == roots){
//cout << "here!\n";
activeEdge ++;
activeLength --;
}
else{
activeNode = activeNode ->suffixLink;
//cout << "[" << activeNode -> st << " " << activeNode -> ed << "]" << endl;
}
}
}
}
}
void print_dfs(node* root){
int enter = 0;
for(int j = 0; j < 256; j++)
if(root -> child[j]) print_dfs(root -> child[j]), enter++;
if(!enter) cout << "[" << root -> st << " " << root -> ed << "] ";
}
vector<int> ans;
void dfs(node* root, int cnt){
//cout << root->st << " " << cnt << endl;
if(root -> ed == last) root -> ed = s.length() - 1;
int enter = 0;
for(int j = 0; j < 256; j++)
if(root -> child[j]) dfs(root -> child[j], cnt+(root->ed - root->st + 1)), enter++;
if(!enter) ans.push_back(s.length() - cnt - (root -> ed - root -> st));
}
void build(){
roots = new node(-1, -1);
activeNode = roots;
for(int j = 0; j < s.length(); j++)
startPhase(j);
print_dfs(roots);
dfs(roots, 0);
}
int main(){
cin >> s;
s += '$';
//cout << s[47] << " " << s[34] << " " << s[2] << " " << s[24] << " " << s[55] << endl;
build();
for(int j = 1; j < ans.size(); j++)
cout << ans[j] << " ";
cout << endl;
return 0;
}