//lg p3809 sa模板题
//Copyright yeyou26

//额外数据测试lcp
//input:aabaaaab
//output:sa:4 5 6 1 7 2 8 3 
//      lcp:0 3 2 3 1 2 0 1 
#include<bits/stdc++.h>
using namespace std;

#define w where

const int N = (int)3e6;

int n,m=256;//后缀个数 桶个数(m初始值为值域(应该是吧))
int where[N];//第i个后缀在哪个桶里
int y[N];//临时数组
int c[N];//计数排序的计数数组
int sa[N];//排名为i的后缀
int rk[N];//第i个后缀的排名
int lcp[N];//排名为i的后缀跟排名为i-1的后缀的最长公共前缀的长度

char s[N];

void init();
void get_sa();
void get_lcp();

int main()
{
    freopen("working.in","r",stdin);
    freopen("working.out","w",stdout);
    init();
    get_sa();
    for(int i=1;i<=n;i++) printf("%d ",sa[i]);
    printf("\n");
    get_lcp();
    for(int i=1;i<=n;i++) printf("%d ",lcp[i]);
    return 0;
}

void init()
{
    cin>>(s+1);
    n=strlen(s+1);
}

//Function Implementation

void get_lcp()
{
    for(int i=1;i<=n;i++) rk[sa[i]]=i;
    for(int i=1,k=0;i<=n;i++) //枚举第i个后缀
    {
        if(rk[i]==1) continue;//排名为1的后缀的lcp=0
        if(k) k--; //定理:lcp[rk[i]]>=lcp[rk[i-1]]-1;
        int j=sa[rk[i]-1]; //从排名上看,i后缀的前临后缀j
        while(i+k<=n && j+k<=n && s[i+k]==s[j+k]) k++;//暴力枚举
        lcp[rk[i]]=k;
    }
}

void get_sa()
{
    //第一次计数排序,按第一个字母排
    for(int i=1;i<=n;i++) c[w[i]=s[i]]++;
    for(int i=1;i<=m;i++) c[i]+=c[i-1];
    for(int i=n;i>=1;i--) sa[c[w[i]]--]=i;
    for(int k=1;k<=n;k<<=1)
    {
        //按 后半段字符串 进行计数排序
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++) y[i]=sa[i];
        for(int i=1;i<=n;i++) c[w[y[i]+k]]++;
        for(int i=1;i<=m;i++) c[i]+=c[i-1];
        for(int i=n;i>=1;i--) sa[c[w[y[i]+k]]--]=y[i];
        //按 前半段字符串 进行计数排序
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++) y[i]=sa[i];
        for(int i=1;i<=n;i++) c[w[y[i]]]++;
        for(int i=1;i<=m;i++) c[i]+=c[i-1];
        for(int i=n;i>=1;i--) sa[c[w[y[i]]]--]=y[i];
        //把排好序的 长度为2k的字符串 放到桶里 并 重新计算桶的个数
        m=0;
        for(int i=1;i<=n;i++) y[i]=w[i];
        for(int i=1;i<=n;i++)
        {
            if(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) w[sa[i]]=m;
            else w[sa[i]]=++m;
        }
        if(m==n) break; //桶个数跟后缀一样多,说明已经排好了
    }
}