#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];

void solve()
{
  //  printf("%d\n",n);
    memset(cnt,0,sizeof cnt);
    memset(vis,0,sizeof vis);
    //for(int i=1;i<n;i++)
     //   printf("%d ",height[i]);
   // puts("");
    int len=0;
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]+sa[i-1]==n-1)len=max(height[i],len);
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]+sa[i] == n-1)len=max(height[i],len);
    }
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i-1]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
   /* for(int i=1;i<=len;i++)
        printf("%d ",cnt[i]);
    puts("");*/
    int ans=0;
    if(vis[len])ans++;
    for(int i=len-1;i>=1;i--)
    {
        if(vis[i])ans++;
        cnt[i]+=cnt[i+1];
    }

    printf("%d\n",ans+1);
    for(int i=1;i<=len;i++)
    {
        if(!vis[i])continue;
        printf("%d %d\n",i,cnt[i]+1);
    }
    printf("%d %d\n",n-1,1);
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}
/*
aaaaaxaaaaaaaaaa
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];

void solve()
{
    bool found=false;
    for(int i=1; i<n; i++)
    {
        if(height[i] ==0 )
        {
            if(found)
            {
                int ans=0;
                for(int i=n-1; i>=1; i--)
                {
                    cnt[i]+=cnt[i+1];
                    if(vis[i])ans++;
                }
                printf("%d\n",ans+1);
                for(int i=1; i<n; i++)
                {
                    if(vis[i])printf("%d %d\n",i,cnt[i]+1);
                }
                printf("%d %d\n",n-1,1);
                return;
            }
            else
            {
                memset(cnt,0,sizeof cnt);
                memset(vis,0,sizeof vis);
                if(sa[i]==0)found=true;
            }
        }
        else
        {
            if(sa[i]==0)found=true;
            vis[height[i]]=1;
            cnt[height[i]]++;
        }
    }
    if(found)
    {
        for(int i=n-1; i>=1; i--)
        {
            cnt[i]+=cnt[i+1];
        }
        for(int i=1; i<n; i++)
        {
            if(vis[i])printf("%d %d\n",i,cnt[i]+1);
        }
        printf("%d %d\n",n-1,1);
    }
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];
int f[maxn][30];

void RMQINIT()
{
    for(int i=0;i<n;i++)
    f[i][0]=height[i];

    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}

int RMQ(int l,int r)
{
    int k=floor(log(r-l+1.0)/log(2.0));
    return min(f[l][k],f[r+1-(1<<k)][k]);
}

void solve()
{
    memset(cnt,0,sizeof cnt);
    memset(vis,0,sizeof vis);
    RMQINIT();
    int len=0;
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]+sa[i-1]==n-1)
        {
            len=max(RMQ(rank[0],i+1),len);
            //break;
        }
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]+sa[i] == n-1)
        {
            len=max(RMQ(rank[0],i),len);
            //break;
        }
    }
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i-1]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
   /* for(int i=1;i<=len;i++)
        printf("%d ",cnt[i]);
    puts("");*/
    int ans=0;
    if(vis[len])ans++;
    for(int i=len-1;i>=1;i--)
    {
        if(vis[i])ans++;
        cnt[i]+=cnt[i+1];
    }

    printf("%d\n",ans+1);
    for(int i=1;i<=len;i++)
    {
        if(!vis[i])continue;
        printf("%d %d\n",i,cnt[i]+1);
    }
    printf("%d %d\n",n-1,1);
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}
/*
aaaaaxaaaaaaaaaa
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];

void solve()
{
    bool found=false;
    for(int i=1; i<n; i++)
    {
        if(height[i] ==0 )
        {
            if(found)
            {
                int ans=0;
                for(int i=n-1; i>=1; i--)
                {
                    cnt[i]+=cnt[i+1];
                    if(vis[i])ans++;
                }
                printf("%d\n",ans+1);
                for(int i=1; i<n; i++)
                {
                    if(vis[i])printf("%d %d\n",i,cnt[i]+1);
                }
                printf("%d %d\n",n-1,1);
                return;
            }
            else
            {
                memset(cnt,0,sizeof cnt);
                memset(vis,0,sizeof vis);
                if(sa[i]==0)found=true;
            }
        }
        else
        {
            if(sa[i]==0)found=true;
            vis[height[i]]=1;
            cnt[height[i]]++;
        }
    }
    if(found)
    {
        int ans=0;
        for(int i=n-1; i>=1; i--)
        {
            cnt[i]+=cnt[i+1];
            if(vis[i])ans++;
        }
        printf("%d\n",ans+1);
        for(int i=1; i<n; i++)
        {
            if(vis[i])printf("%d %d\n",i,cnt[i]+1);
        }
        printf("%d %d\n",n-1,1);
    }
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];

void solve()
{
  //  printf("%d\n",n);
    memset(cnt,0,sizeof cnt);
    memset(vis,0,sizeof vis);
    //for(int i=1;i<n;i++)
     //   printf("%d ",height[i]);
   // puts("");
    int len=height[rank[0]];
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i-1]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i-1]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
   /* for(int i=1;i<=len;i++)
        printf("%d ",cnt[i]);
    puts("");*/
    int ans=0;
    if(vis[len])ans++;
    for(int i=len-1;i>=1;i--)
    {
        if(vis[i])ans++;
        cnt[i]+=cnt[i+1];
    }

    printf("%d\n",ans+1);
    for(int i=1;i<=len;i++)
    {
        if(!vis[i])continue;
        printf("%d %d\n",i,cnt[i]+1);
    }
    printf("%d %d\n",n-1,1);
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}
/*
aaaaaxaaaaaaaaaa
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];

void solve()
{
  //  printf("%d\n",n);
    memset(cnt,0,sizeof cnt);
    memset(vis,0,sizeof vis);
    //for(int i=1;i<n;i++)
     //   printf("%d ",height[i]);
   // puts("");
    int len=height[rank[0]];
    for(int i=rank[0];i>0;i--)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i-1]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
    for(int i=rank[0]+1;i<n;i++)
    {
        if(height[i]==0)break;
        if(height[i]+sa[i]==n-1)vis[height[i]]=1;
        if(height[i]>=len)cnt[len]++;
        else cnt[height[i]]++;
    }
   /* for(int i=1;i<=len;i++)
        printf("%d ",cnt[i]);
    puts("");*/
    int ans=0;
    if(vis[len])ans++;
    for(int i=len-1;i>=1;i--)
    {
        if(vis[i])ans++;
        cnt[i]+=cnt[i+1];
    }

    printf("%d\n",ans+1);
    for(int i=1;i<=len;i++)
    {
        if(!vis[i])continue;
        printf("%d %d\n",i,cnt[i]+1);
    }
    printf("%d %d\n",n-1,1);
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}
/*
aaaaaxaaaaaaaaaa
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 300005
#define debug puts("here!")
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *x=t1,*y=t2;
    for(int i=0; i<m; i++)c[i]=0;
    for(int i=0; i<n; i++)c[x[i]=str[i]]++;
    for(int i=1; i<m; i++)c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
    for(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int cnt[maxn];
int vis[maxn];
int f[maxn][30];

void RMQINIT()
{
    for(int i=0;i<n;i++)
    f[i][0]=height[i];

    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}

int RMQ(int l,int r)
{
    int k=floor(log(r-l+1.0)/log(2.0));
    return min(f[l][k],f[r+1-(1<<k)][k]);
}
struct node
{
    int len,time;
}fans[maxn];
int top=0;
void solve()
{
    RMQINIT();

    for(int i=1;i<n;i++)
    {
        int l,r;

        if( i<rank[0] )
            l=i+1,r=rank[0];
        else if(i>rank[0]) l=rank[0]+1,r=i;
        else continue;

        int comlen=RMQ(l,r);
      //  printf("len = %d\n",comlen);
        if( sa[i] + comlen == n-1 )
        {
            int L=i,R=n-1,ans;
            while(L<=R)
            {
                int mid=(L+R)>>1;
              //  printf("%d\n",RMQ(i+1,mid));
                if(RMQ(i+1,mid)>=comlen)
                {
                    ans=mid;
                    L=mid+1;
                }
                else R=mid-1;
            }

            fans[top].len=comlen;
            fans[top++].time=ans-i+1;
        }
    }
    fans[top].len=n-1;
    fans[top++].time=1;
    printf("%d\n",top);
    for(int i=0;i<top;i++)
        printf("%d %d\n",fans[i].len,fans[i].time);
}
int main()
{
    scanf("%s",str);
    n=strlen(str);
    str[n]=0;
    n++;

    suffix(128);
    getheight();

    solve();
    return 0;
}
/*
GERALDPAVELGERALDPAVEL

aaaaaxaaaaaaaaaa
*/


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 99991;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], d[maxn], ans[maxn], cnt;
char s[maxn];
int dfs(int k) {
    if (d[k]!=-1) {
        return d[k];
    }
    return d[k]=dfs(f[k])+1;
}
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
//        int k = f[i+1];
//        while (k) {
//            ++a[k];
//            k = f[k];
//        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    for (int i=M; i>0; --i) {
        ++d[i];
        d[f[i]] += d[i];
        a[i] = d[i];
    }
    hash_t pre = 0, suf = 0, L = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        L*=seed;
        if (pre==suf) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 99991;
const int seed1 = 131;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], d[maxn], ans[maxn], cnt;
char s[maxn];
int dfs(int k) {
    if (d[k]!=-1) {
        return d[k];
    }
    return d[k]=dfs(f[k])+1;
}
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
//        int k = f[i+1];
//        while (k) {
//            ++a[k];
//            k = f[k];
//        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    for (int i=M; i>0; --i) {
        ++d[i];
        d[f[i]] += d[i];
        a[i] = d[i];
    }
    hash_t pre = 0, suf = 0, L = 1, pre1 = 0, suf1 = 0, L1 = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        pre1 = pre1*seed1+s[i];
        suf = suf+s[M-i-1]*L1;
        L1*=seed1;
        L*=seed;
        if (pre==suf && pre1==suf1) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 131;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], d[maxn], ans[maxn], cnt;
char s[maxn];
int dfs(int k) {
    if (d[k]!=-1) {
        return d[k];
    }
    return d[k]=dfs(f[k])+1;
}
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
//        int k = f[i+1];
//        while (k) {
//            ++a[k];
//            k = f[k];
//        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    for (int i=M; i>0; --i) {
        ++d[i];
        d[f[i]] += d[i];
        a[i] = d[i];
    }
    hash_t pre = 0, suf = 0, L = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        L*=seed;
        if (pre==suf) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 99991;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], ans[maxn], cnt;
char s[maxn];
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
        int k = f[i+1];
        while (k) {
            ++a[k];
            k = f[k];
        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    hash_t pre = 0, suf = 0, L = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        L*=seed;
        if (pre==suf) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]+1);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 99991;
const int seed1 = 131;
const int mod = 999983;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], d[maxn], ans[maxn], cnt;
char s[maxn];
int dfs(int k) {
    if (d[k]!=-1) {
        return d[k];
    }
    return d[k]=dfs(f[k])+1;
}
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
//        int k = f[i+1];
//        while (k) {
//            ++a[k];
//            k = f[k];
//        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    for (int i=M; i>0; --i) {
        ++d[i];
        d[f[i]] += d[i];
        a[i] = d[i];
    }
    hash_t pre = 0, suf = 0, L = 1, pre1 = 0, suf1 = 0, L1 = 1;
    hash_t pre2 = 0, suf2 = 0, L2 = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        pre1 = pre1*seed1+s[i];
        suf1 = suf1+s[M-i-1]*L1;
        pre2 = (pre2*113+s[i])%mod;
        suf2 = (suf2+s[M-i-1]*L2%mod)%mod;
        L1*=seed1;
        L2 = L2*113%mod;
        L*=seed;
        if (pre==suf && pre1==suf1 && suf2==pre2) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int N, a[maxn], pos[maxn], p[maxn], cnt, hehe[maxn][2], ans[maxn*5][2];
bool vis[maxn];
void getp() {
    for (int i=2; i<maxn; ++i) {
        if (!vis[i]) {
            p[cnt++] = i;
        }
        for (int j=0; j<cnt; ++j) {
            long long temp = 1LL*p[j]*i;
            if (temp>=maxn) {
                break;
            }
            vis[temp] = 1;
            if (i%p[j]==0) {
                break;
            }
        }
    }
    hehe[4][0] = 2;
    hehe[4][1] = 2;
    vis[1] = 1;
    for (int i=6; i<maxn; i+=2) {
        int k = upper_bound(p, p+cnt, i)-p-1;
        for (; p[k]*2>=i; --k) {
            if (!vis[i-p[k]]) {
                hehe[i][0] = p[k];
                hehe[i][1] = i-p[k];
                break;
            }
        }
    }
}
inline void myswap(int i, int j) {
    swap(pos[a[i]], pos[a[j]]);
    swap(a[i], a[j]);
}
int main()
{
    getp();
    scanf ("%d", &N);
    for (int i=1; i<=N; ++i) {
        scanf ("%d", &a[i]);
        pos[a[i]] = i;
    }
    int k = 0;
    for (int i=1; i<=N; ++i) {
        if (a[i]!=i) {
            if (pos[i]-i+1==2) {
                ++k;
                ans[k][0] = i;
                ans[k][1] = pos[i];
                myswap(i, pos[i]);
            } else {
                if ((pos[i]-i+1)%2==0) {
                    ++k;
                    ans[k][0] = pos[i];
                    ans[k][1] = pos[i]-1;
                    myswap(ans[k][0], ans[k][1]);
                }
                {
                    int t = pos[i]-i+2;
                    ++k;
                    ans[k][1] = pos[i]-hehe[t][0]+1;
                    ans[k][0] = pos[i];
                    myswap(ans[k][0], ans[k][1]);
                    ++k;
                    ans[k][1] = pos[i]-hehe[t][1]+1;
                    ans[k][0] = pos[i];
                    myswap(ans[k][0], ans[k][1]);
                }
            }
        }
    }
    printf ("%d\n", k);
    for (int i=1; i<=k; ++i) {
        if (ans[i][0]>ans[i][1]) {
            swap(ans[i][0], ans[i][1]);
        }
        printf ("%d %d\n", ans[i][0], ans[i][1]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int seed = 99991;
const int seed1 = 131;
typedef unsigned long long hash_t;
int T, M, f[maxn], a[maxn], d[maxn], ans[maxn], cnt;
char s[maxn];
int dfs(int k) {
    if (d[k]!=-1) {
        return d[k];
    }
    return d[k]=dfs(f[k])+1;
}
void getFail() {
    f[0] = f[1] = 0;
    for (int i=1; i<=M; i++) {
        int j = f[i];
        while (j && s[i]!=s[j]) j = f[j];
        f[i+1] = s[i]==s[j] ? j+1 : 0;
       // if (i!=f[i+1]) {
//        int k = f[i+1];
//        while (k) {
//            ++a[k];
//            k = f[k];
//        }
       // }
    }
}
int main()
{
    scanf ("%s", s);
    M = strlen(s);
    getFail();
    for (int i=M; i>0; --i) {
        ++d[i];
        d[f[i]] += d[i];
        a[i] = d[i];
    }
    hash_t pre = 0, suf = 0, L = 1, pre1 = 0, suf1 = 0, L1 = 1;
    for (int i=0; i<M; ++i) {
        pre = pre*seed+s[i];
        suf = suf+s[M-i-1]*L;
        pre1 = pre1*seed1+s[i];
        suf1 = suf1+s[M-i-1]*L1;
        L1*=seed1;
        L*=seed;
        if (pre==suf && pre1==suf1) {
            //printf ("%d\n", i+1);
            ans[cnt++] = i+1;
        }
    }
    printf ("%d\n", cnt);
    for (int i=0; i<cnt; ++i) {
        printf ("%d %d\n", ans[i], a[ans[i]]);
    }
    return 0;
}


/*#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
vector<pair<int,int> >ans;
void GetNext()
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<l)
    {
        while(k>-1&&str[j]!=str[k])
            k=next[k];
        next[++j]=++k;
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    GetNext();
    for(int i=1; i<=l; ++i)
        printf("%d ",next[i]);
    putchar('\n');
    memset(cnt,0,sizeof(cnt));
    for(int i=1; i<=l; ++i)
        ++cnt[next[i]];
    for(int pos=l; pos>0; pos=next[pos])
        ans.push_back(make_pair(pos,cnt[next[pos]]));
    sort(ans.begin(),ans.end());
    printf("%d\n",ans.size());
    for(int i=0; i<ans.size(); ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l;
map<int,int> cnt;
map<int,int>::iterator it;
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    int k=1;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    putchar('\n');
    for(int i=0; i<l; ++i)
        if(next[i]>0)
            ++cnt[next[i]];
    for(it=cnt.begin(); it!=cnt.end(); ++it)
        ans.push_back(make_pair(it->first,it->second));
    for(int i=ans.size()-1; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",ans.size());
    for(int i=0; i<ans.size(); ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
bool ok[MAXN];
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0,k=1;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    memset(ok,false,sizeof(ok));
    for(int i=0; i<l; ++i)
        ok[l-i]=next[i]==l-i;
    /*for(int i=0; i<l; ++i)
        printf("%d ",next[i]);
    putchar('\n');
    for(int i=1; i<=l; ++i)
        printf("%d ",ok[i]);
    putchar('\n');*/
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<l; ++i)
        if(next[i]>0&&ok[next[i]])
            ++cnt[next[i]];
    for(int i=1; i<=l; ++i)
        if(cnt[i]>0)
            ans.push_back(make_pair(i,cnt[i]));
    int as=ans.size();
    for(int i=as-2; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",as);
    for(int i=0; i<as; ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
bool ok[MAXN];
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0,k=1;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<l; ++i)
        ok[l-i]=next[i]==l-i;
    for(int i=0; i<l; ++i)
        if(ok[next[i]])
            ++cnt[next[i]];
    for(int i=1; i<=l; ++i)
        if(cnt[i]>0)
            ans.push_back(make_pair(i,cnt[i]));
    int as=ans.size();
    for(int i=as-2; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",as);
    for(int i=0; i<as; ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
bool ok[MAXN];
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0,k=1;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    memset(ok,false,sizeof(ok));
    for(int i=0; i<l; ++i)
        if(next[i]==l-i)
            ok[next[i]]=true;
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<l; ++i)
        if(next[i]>0&&ok[next[i]])
            ++cnt[next[i]];
    for(int i=1; i<=l; ++i)
        if(cnt[i]>0)
            ans.push_back(make_pair(i,cnt[i]));
    int as=ans.size();
    for(int i=as-2; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",as);
    for(int i=0; i<as; ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
bool ok[MAXN];
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0,k=1;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<l; ++i)
        if(next[i]>0)
            ++cnt[next[i]];
    for(int i=1; i<=l; ++i)
        if(cnt[i]>0)
            ans.push_back(make_pair(i,cnt[i]));
    int as=ans.size(),num=0;
    for(int i=as-2; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    for(int i=0; i<l; ++i)
        ok[l-i]=next[i]==l-i;
    for(int i=0; i<as; ++i)
        if(ok[ans[i].first])
            ++num;
    printf("%d\n",num);
    for(int i=0; i<as; ++i)
        if(ok[ans[i].first])
            printf("%d %d\n",ans[i].first,ans[i].second);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    int k=1;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<l; ++i)
        if(next[i]>0)
            ++cnt[next[i]];
    for(int i=1; i<=l; ++i)
        if(cnt[i]>0)
            ans.push_back(make_pair(i,cnt[i]));
    int as=ans.size();
    for(int i=as-2; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",as);
    for(int i=0; i<as; ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


/*#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l,cnt[MAXN];
vector<pair<int,int> >ans;
void GetNext()
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<l)
    {
        while(k>-1&&str[j]!=str[k])
            k=next[k];
        next[++j]=++k;
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    GetNext();
    for(int i=1; i<=l; ++i)
        printf("%d ",next[i]);
    putchar('\n');
    memset(cnt,0,sizeof(cnt));
    for(int i=1; i<=l; ++i)
        ++cnt[next[i]];
    for(int pos=l; pos>0; pos=next[pos])
        ans.push_back(make_pair(pos,cnt[next[pos]]));
    sort(ans.begin(),ans.end());
    printf("%d\n",ans.size());
    for(int i=0; i<ans.size(); ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int MAXN=100005;
char str[MAXN];
int next[MAXN],l;
map<int,int> cnt;
map<int,int>::iterator it;
vector<pair<int,int> >ans;
void pre_EKMP()
{
    next[0]=l;
    int j=0;
    while(j+1<l&&str[j]==str[j+1])
        ++j;
    next[1]=j;
    int k=1;
    for(int i=2; i<l; ++i)
    {
        int p=next[k]+k-1,L=next[i-k];
        if(i+L<p+1)
            next[i]=L;
        else
        {
            j=max(0,p-i+1);
            while(i+j<l&&str[i+j]==str[j])
                ++j;
            next[i]=j;
            k=i;
        }
    }
}
int main()
{
    scanf("%s",str);
    l=strlen(str);
    pre_EKMP();
    for(int i=0; i<l; ++i)
        if(next[i]>0)
            ++cnt[next[i]];
    for(it=cnt.begin(); it!=cnt.end(); ++it)
        ans.push_back(make_pair(it->first,it->second));
    for(int i=ans.size()-1; i>=0; --i)
        ans[i].second+=ans[i+1].second;
    printf("%d\n",ans.size());
    for(int i=0; i<ans.size(); ++i)
        printf("%d %d\n",ans[i].first,ans[i].second);
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100005
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100005
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
int stp;
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = stp-1; i >= 0 && x < N && y < N; i--){
        if(P[i][x] == P[i][y]){
            //printf("i:%d x:%d y:%d val:%d\n",i,x,y,P[i][x]);
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();
    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            L[i].a[1] = (i+cnt) < N ? P[j-1][i+cnt] : -1;

        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
          P[j][L[i].id] = (L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1]) ? P[j][L[i-1].id] : P[j][L[i-1].id] + 1;
        }
    }
    stp = j;
    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;

    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 19; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;

    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 18; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}
int lcp[Z];
void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
        if(i != 0)
        lcp[i] = LCP(L[i].id, L[i-1].id);
    }

    int now,ans,n2,j,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1; now = N;
    ans = 1; j=r; n2= N;
    for(i = r-1; i >= 0; i--){
        now = min(lcp[i+1],now);
        len = N - L[i].id;
        if(now != len) continue;
        while(j < N-1){
            if(min(n2,lcp[j+1])>=len){
                j++;
                n2 = min(n2,lcp[j]);
            }
            else break;
        }
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r; now = N; n2 = N;
    for(j = r+1; j < N; j++){
        now = min(lcp[j],now);
        len = N - L[j].id;
        if(now != len) continue;
        while(i > 0){
            if(min(n2,lcp[i])>=len){
                n2 = min(n2,lcp[i]);
                i++;
            }
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100005
#define         MOD     1000000007
#define         MAXLG       17
#define         MAXN        100005
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 17; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();
    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }
    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;
    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100005
#define         MOD     1000000007
#define         MAXLG       17
#define         MAXN        100005
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
int stp;
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = stp-1; i >= 0 && x < N && y < N; i--){
        if(P[i][x] == P[i][y]){
            //printf("i:%d x:%d y:%d val:%d\n",i,x,y,P[i][x]);
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();
    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            L[i].a[1] = (i+cnt) < N ? P[j-1][i+cnt] : -1;

        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
          P[j][L[i].id] = (L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1]) ? P[j][L[i-1].id] : P[j][L[i-1].id] + 1;
        }
    }
    stp = j;
    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;

    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 18; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}
int lcp[Z];
void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
        if(i != 0)
        lcp[i] = LCP(L[i].id, L[i-1].id);
    }

    int now,ans,n2,j,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1; now = N;
    ans = 1; j=r; n2= N;
    for(i = r-1; i >= 0; i--){
        now = min(lcp[i+1],now);
        len = N - L[i].id;
        if(now != len) continue;
        while(j < N-1 && min(n2,lcp[j+1])>=len){
                j++;
                n2 = min(n2,lcp[j]);
        }
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r; now = N; n2 = N;
    for(j = r+1; j < N; j++){
        now = min(lcp[j],now);
        len = N - L[j].id;
        if(now != len) continue;
        while(i > 0 && min(n2,lcp[i])>=len){
                n2 = min(n2,lcp[i]);
                i--;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <cmath>
#include <sstream>
#include <set>
#include <utility>
#include <queue>
#include <cassert>
#include <ctime>
#include <stack>
using namespace std;

#define PB push_back
#define SZ size()
#define all(v) v.begin(), v.end()
#define REP(i, n) for(int i = 0; i < (int)n; i++)
#define ITR(i, j, n) for(int i = j; i < (int)n; i++)
#define mem(array, val) memset(array, val, sizeof(array))
#define READ(filename) freopen(filename, "r", stdin)
#define WRITE(filename) freopen(filename, "w", stdout)
#define Pii pair <int, int>
#define Fr first
#define Sc second
#define Long long long

#define MAX 100005
#define INF 1000000010
#define MOD 1000000007LL

struct data {
  Pii tup;
  int p;

  bool operator < (const data &b) const
  {
    return tup < b.tup;
  }
} L[MAX];
int srt_indx[21][MAX], n, lp[MAX], cnt[MAX];
char str[MAX];
int rec[MAX];

int main()
{
  scanf("%s", str);
  n = strlen(str);
  REP(i, n)
    srt_indx[0][i] = str[i] - 'A';

  int step, done;
  for(step = 1, done = 1; (done / 2) < n; done *= 2, step++) {
    REP(i, n) {
      L[i].tup.Fr = srt_indx[step-1][i];
      L[i].tup.Sc = (i + done < n) ? srt_indx[step-1][i + done] : -1;
      L[i].p = i;
    }
    sort(L, L+n);

    REP(i, n) {
      srt_indx[step][L[i].p] = (i>0 && L[i].tup.Fr == L[i-1].tup.Fr && L[i].tup.Sc == L[i-1].tup.Sc) ? srt_indx[step][L[i-1].p] : i;
    }
  }

  ITR(i, 0, n) {
    int x = 0, y = L[i].p;
    if(x == y)
      continue;
    for(int j = step-1; j >= 0 && x < n && y < n; j--) {
      if(srt_indx[j][x] == srt_indx[j][y]) {
        x += (1 << j);
        y += (1 << j);
        lp[i] += (1 << j);
      }
    }

    cnt[lp[i]]++;
  }

  cnt[n] = 1;
  for(int i = n-1; i > 0; i--)
    cnt[i] += cnt[i+1];

  int ret = 1;
  rec[n] = 1;
  for(int i = 0; i < n ; i++){
    if(L[i].p == 0) continue;
    if(lp[i] != (n - L[i].p))continue;
    ret++;
    rec[lp[i]] = cnt[lp[i]];
  }

  cout<<ret<<endl;
    for(int len = 1; len <= n; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
  return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 19; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();
    cout<<N<<endl;
    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    for(i = 0; i < 100000; i++)
            str[i] = 'A';
    str[100000] = NULL;

    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;

    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    16 May
    Suffix Array
*/

#include <bits/stdc++.h>
#define         MAX_LG      20
#define         MAX_N       100005
#define         fr          first
#define         sc          second
using namespace std;
typedef pair<int,int>  pii;
struct node{
    int id; pii a;
};
bool cmp(node a, node b){
    return a.a < b.a;
}
char S[MAX_N];
node L[MAX_N];
int lcp[MAX_N],rec[MAX_N];

int P[MAX_LG][MAX_N];
int main(){
    int N,i,stp,cnt,x,y;

    cin >> S;
    N = strlen(S);

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(stp =1, cnt = 1; (cnt/2) < N ; stp++,cnt*=2){
        for(i = 0; i < N; i++){
            L[i].id = i;
            L[i].a.fr = P[stp-1][i];
            L[i].a.sc =  i+cnt < N ? P[stp-1][i+cnt] : -1;
        }
        sort(L, L+ N,cmp);

        P[stp][L[0].id] = 0;
        for(i = 1; i < N; i++){
            P[stp][L[i].id] = (L[i].a == L[i-1].a) ? P[stp][L[i-1].id] : P[stp][L[i-1].id]+1;
        }
    }

    int j,r;
    for(i = 1; i < N; i++){
        x = L[i].id;  y = L[i-1].id;
        lcp[i] = 0;
        if(L[i].id == 0) r = i;
        for(j = stp-1; j >= 0 && x < N && y < N; j--){
            if(P[j][x] == P[j][y]){
                lcp[i] += (1<<j);
                x+=(1<<j);
                y+=(1<<j);
            }
        }
    }

    int now,ans,n2,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1; now = N;
    ans = 1; j=r; n2= N;
    for(i = r-1; i >= 0; i--){
        now = min(lcp[i+1],now);
        len = N - L[i].id;
        if(now != len) continue;
        while(j < N-1){
            if(min(n2,lcp[j+1])>=len){
                j++;
                n2 = min(n2,lcp[j]);
            }
            else break;
        }
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r; now = N; n2 = N;
    for(j = r+1; j < N; j++){
        now = min(lcp[j],now);
        len = N - L[j].id;
        if(now != len) continue;
        while(i > 0){
            if(min(n2,lcp[i])>=len){
                n2 = min(n2,lcp[i]);
                i++;
            }
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }

    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
int lcp[Z],rec[Z];
char S[Z];
int main(){

    int i,j,cnt;
    scanf("%s",S);
    N  = strlen(S);

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }
    int stp,r,x,y;
    stp = j-1;

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
    }

    for(i = 0; i < N; i++){
        x = L[i].id; y = 0;
        lcp[i] = 0;
        for(j = stp ; j >= 0 && x < N && y < N; j--){
            if(P[j][x] == P[j][y]){
                lcp[i] += (1<<j);
                x += (1<<j);
                y += (1<<j);
            }
        }
    }

    int now,ans,n2,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1;
    ans = 1; j=r;
    for(i = r-1; i >= 0; i--){
        len = N - L[i].id;
        if(lcp[i] != len) continue;
        while(j < N-1 && lcp[j+1] >=len) j++;
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r;
    for(j = r+1; j < N; j++){
        len = N - L[j].id;
        if(lcp[j] != len) continue;
        while(i > 0 && lcp[i-1]>=len) i--;
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    16 May
    Suffix Array
*/

#include <bits/stdc++.h>
#define         MAX_LG      20
#define         MAX_N       100005
#define         fr          first
#define         sc          second
#define         CHK         cout<<"OK"<<endl;
using namespace std;
typedef pair<int,int>  pii;
struct node{
    int id; pii a;
};
bool cmp(node a, node b){
    return a.a < b.a;
}
char S[MAX_N];
node L[MAX_N];
int lcp[MAX_N],rec[MAX_N];

int P[MAX_LG][MAX_N];
int main(){
    int N,i,stp,cnt,x,y;

    cin >> S;
    N = strlen(S);

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(stp =1, cnt = 1; (cnt/2) < N ; stp++,cnt*=2){
        for(i = 0; i < N; i++){
            L[i].id = i;
            L[i].a.fr = P[stp-1][i];
            L[i].a.sc =  i+cnt < N ? P[stp-1][i+cnt] : -1;
        }
        sort(L, L+ N,cmp);

        P[stp][L[0].id] = 0;
        for(i = 1; i < N; i++){
            P[stp][L[i].id] = (L[i].a == L[i-1].a) ? P[stp][L[i-1].id] : P[stp][L[i-1].id]+1;
        }
    }

    int j,r;
    for(i = 0; i < N; i++){
        x = L[i].id;  y = L[i-1].id;
        lcp[i] = 0;
        if(L[i].id == 0) r = i;
        if(x == y){
            lcp[i] = N-x;
            continue;
        }
        for(j = stp-1; j >= 0 && x < N && y < N; j--){
            if(P[j][x] == P[j][y]){
                lcp[i] += (1<<j);
                x+=(1<<j);
                y+=(1<<j);
            }
        }
    }

    int now,ans,n2,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1; now = N;
    ans = 1; j=r; n2= N;
    for(i = r-1; i >= 0; i--){
        now = min(lcp[i+1],now);
        len = N - L[i].id;
        if(now != len) continue;
        while(j < N-1){
            if(min(n2,lcp[j+1])>=len){
                j++;
                n2 = min(n2,lcp[j]);
            }
            else break;
        }
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r; now = N; n2 = N;
    for(j = r+1; j < N; j++){
        now = min(lcp[j],now);
        len = N - L[j].id;
        if(now != len) continue;
        while(i > 0){
            if(min(n2,lcp[i])>=len){
                n2 = min(n2,lcp[i]);
                i++;
            }
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }

    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 19; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}

void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();
    cout<<N<<endl;
    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
    }

    int j,len,now;
    memset(rec, 0, sizeof(rec));
    i = r;
    j = r;
    rec[N] = 1;
    int ans; ans = 1;

    for(len = N; len > 0; len--){
        i  = pos[N-len];
        if(i >= r) continue;
        now = LCP(L[i].id, L[r].id);
        if(now != len) continue;
        while(j < N-1){
            if(LCP(L[j+1].id,L[i].id)>=len) j++;
            else break;
        }
        rec[len] = j - i + 1;
       ans++;
    }

    i = r; j = r;
    for(len = N; len>0; len--){
        j = pos[N-len];
        if(j <= r) continue;
        now = LCP(L[r].id, L[j].id);
        if(now != len) continue;
        while(i > 0){
            if(LCP(L[i-1].id, L[j].id) >= len) i--;
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 19; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}
int lcp[Z];
void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int pos[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);
    N = S.size();

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
        pos[L[i].id] = i;
        if(i != 0)
        lcp[i] = LCP(L[i].id, L[i-1].id);
    }

    int now,ans,n2,j,len;

    memset(rec,0,sizeof(rec));
    rec[N]  = 1; now = N;
    ans = 1; j=r; n2= N;
    for(i = r-1; i >= 0; i--){
        now = min(lcp[i+1],now);
        len = N - L[i].id;
        if(now != len) continue;
        while(j < N-1){
            if(min(n2,lcp[j+1])>=len){
                j++;
                n2 = min(n2,lcp[j]);
            }
            else break;
        }
        rec[len] = j - i + 1;
        ans ++;
    }

    i = r; now = N; n2 = N;
    for(j = r+1; j < N; j++){
        now = min(lcp[j],now);
        len = N - L[j].id;
        if(now != len) continue;
        while(i > 0){
            if(min(n2,lcp[i])>=len){
                n2 = min(n2,lcp[i]);
                i++;
            }
            else break;
        }
        rec[len] = j - i +1;
        ans++;
        //printf("%d ",len);
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
int lcp[Z],rec[Z],kip[Z];
char S[Z];
int main(){

    int i,j,cnt;
    scanf("%s",S);
    N  = strlen(S);

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }
    int stp,r,x,y;
    stp = j-1;

    for(i = 0; i < N; i++){
        if(L[i].id == 0) r= i;
    }

    for(i = 0; i < N; i++){
        x = L[i].id; y = 0;
        lcp[i] = 0;
        for(j = stp ; j >= 0 && x < N && y < N; j--){
            if(P[j][x] == P[j][y]){
                lcp[i] += (1<<j);
                x += (1<<j);
                y += (1<<j);
            }
        }
        kip[lcp[i]]++;
    }

    for(i = 0; i < N; i++)
        kip[i]+=kip[i+1];

    rec[N]  = 1; int ans=1;
    int len;

    for(i = 0; i < N; i++){
        len = N - L[i].id;
        if(L[i].id == 0 || lcp[i]!=len) continue;
        rec[len] = kip[i];
        ans++;
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <cmath>
#include <sstream>
#include <set>
#include <utility>
#include <queue>
#include <cassert>
#include <ctime>
#include <stack>
using namespace std;

#define PB push_back
#define SZ size()
#define all(v) v.begin(), v.end()
#define REP(i, n) for(int i = 0; i < (int)n; i++)
#define ITR(i, j, n) for(int i = j; i < (int)n; i++)
#define mem(array, val) memset(array, val, sizeof(array))
#define READ(filename) freopen(filename, "r", stdin)
#define WRITE(filename) freopen(filename, "w", stdout)
#define Pii pair <int, int>
#define Fr first
#define Sc second
#define Long long long

#define MAX 100005
#define INF 1000000010
#define MOD 1000000007LL

struct data {
  Pii tup;
  int p;

  bool operator < (const data &b) const
  {
    return tup < b.tup;
  }
} L[MAX];
int srt_indx[21][MAX], n, lp[MAX], cnt[MAX];
char str[MAX];
int rec[MAX];

int main()
{
  scanf("%s", str);
  n = strlen(str);
  REP(i, n)
    srt_indx[0][i] = str[i] - 'A';

  int step, done;
  for(step = 1, done = 1; (done / 2) < n; done *= 2, step++) {
    REP(i, n) {
      L[i].tup.Fr = srt_indx[step-1][i];
      L[i].tup.Sc = (i + done < n) ? srt_indx[step-1][i + done] : -1;
      L[i].p = i;
    }
    sort(L, L+n);

    REP(i, n) {
      srt_indx[step][L[i].p] = (i>0 && L[i].tup.Fr == L[i-1].tup.Fr && L[i].tup.Sc == L[i-1].tup.Sc) ? srt_indx[step][L[i-1].p] : i;
    }
  }

  ITR(i, 1, n) {
    int x = 0, y = i;
    if(x == y)
      continue;
    for(int j = step-1; j >= 0 && x < n && y < n; j--) {
      if(srt_indx[j][x] == srt_indx[j][y]) {
        x += (1 << j);
        y += (1 << j);
        lp[i] += (1 << j);
      }
    }

    cnt[lp[i]]++;
  }
  cnt[n] = 1;
  for(int i = n-1; i > 0; i--)
    cnt[i] += cnt[i+1];

  int ret = 1;
  rec[n] = 1;
  for(int i = 1; i < n ; i++){
     if(lp[i] != (n - i))
      continue;
    ret++;
    rec[lp[i]] = cnt[lp[i]];
  }

  cout<<ret<<endl;
    for(int len = 1; len <= n; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
  return 0;
}


/*
    Date : 15 May   2014

*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define         mp      make_pair
#define         pb      push_back
#define         fr      first
#define         sc      second
#define         Z       100010
#define         MOD     1000000007
#define         MAXLG       20
#define         MAXN        100010
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;

struct node{
    int id, a[2];
};

bool cmp(node a, node b){
    if(a.a[0] != b.a[0]) return a.a[0]< b.a[0];
    return a.a[1] < b.a[1];
}
int P[MAXLG][MAXN],N;
node L[MAXN];
// Finding the Longest Common Prefix.
int LCP(int x, int y){
    int i,ans;
    if(x == y) return N - x;
    ans =  0;

    for(i = 16; i >= 0; i--){
        if(((x + (1<<i)) > N) || ((y + (1<<i))> N)) continue;

        if(P[i][x] == P[i][y]){
            ans = ans + (1<<i);
            x = x + (1<<i);
            y = y + (1<<i);
        }
    }

    return ans;
}
int lcp[Z];
void SuffixArray(string S){
      // Suffix Array
      int i,j,cnt;

    N = S.size();

    for(i = 0; i < N; i++)
        P[0][i] = S[i] - 'A';

    for(j = 1, cnt = 1 ; cnt >> 1 < N ;j++, cnt <<=1){
        for(i = 0; i < N ; i++){
            L[i].id = i;
            L[i].a[0] = P[j-1][i];
            if(i + cnt < N) L[i].a[1] = P[j-1][i+cnt];
            else L[i].a[1] = -1;
        }
        sort(L, L+ N, cmp);
        P[j][L[0].id] = 0;
        for(i = 1; i < N; i++){
            if(L[i].a[0] == L[i-1].a[0] && L[i].a[1] == L[i-1].a[1])
                P[j][L[i].id] = P[j][L[i-1].id];
            else P[j][L[i].id] = P[j][L[i-1].id] + 1;
        }

    }

    return;
}

int kip[Z],rec[Z];
char str[Z];
int main(){

    string S;
    int i,r;

    scanf("%s",str);
    S = str;

    SuffixArray(S);

    for(i = 0; i < N; i++){
        lcp[i] = LCP(L[i].id,0);
       // cout <<lcp[i]<<endl;
        kip[lcp[i]]++;
    }
    for(i = N-1; i>=0; i--)
        kip[i] += kip[i+1];
    int ans,len;

    ans = 0;
    for(i = 0; i < N; i++){
        len = N - L[i].id;
        if(lcp[i] != len) continue;
        rec[len] = kip[lcp[i]];
        ans++;
    }

    cout<<ans<<endl;
    for(len = 1; len <= N; len++){
        if(rec[len]==0) continue;
        printf("%d %d\n",len, rec[len]);
    }
    return 0;
}


*
ID: Labib666
LANG: C++
Contest: Codeforces R246
Task: 4
*/

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define VI vector <int>
#define VLL vector <LL>
#define PQI priority_queue <int>
#define PQLL priority_queue <LL>
#define QI queue <int>
#define QLL queue <LL>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define SZ size()
#define INF 1000000007
#define LINF 1000000000000000007
#define PI 2*asin(1)
#define EPS 1e-9

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     ((A).begin(), (A).end())
#define MEM(A,V)   memset (A, (V), sizeof A)

int gcd (int a, int b){return (b > a) ? gcd (b,a) : (b == 0) ? a : gcd (b, a%b);}
int bitcount (int a) {return (a != 0) ? bitcount(a & (a-1)) + 1 : 0;}
LL bigmod (LL num, LL pow, LL prime) {
    if (pow == 0ll) return 1ll;
    LL ans = bigmod(num, pow/2ll, prime); ans = (ans*ans)%prime;
    if (pow%2ll) ans = (ans*num)%prime; return ans;
}

#define MAXN 100005
#define MAXLG 20

struct Data {
    int    e[2], p;
    bool operator < (const Data &d) const {
        return make_pair(e[0], e[1]) < make_pair(d.e[0], d.e[1]);
    }
} T[MAXN];

int P[MAXLG][MAXN], D[MAXN], N, stp, cnt, i, j;
char A[MAXN];

int B[MAXN];
void U(int pos) {
    while (pos <= N) {
        B[pos]++;
        pos += pos&-pos;
    }
    return;
}
int Q (int pos) {
    int ans = 0;
    while (pos != 0) {
        ans += B[pos];
        pos -= pos&-pos;
    }
    return ans;
}

vector <PII> ans;

int main()
{
    //freopen("input.txt", "r", stdin);
    cin >> A;
    N = strlen (A);

    for (i = 0; i < N; i++)
        P[0][i] = A[i]-'A';

    for (stp = 1, cnt = 1; cnt >> 1 < N; cnt <<= 1, stp++) {
        for (i=0; i<N; i++) {
            T[i].e[0] = P[stp-1][i];
            T[i].e[1] = (i+cnt < N) ? P[stp-1][i+cnt] : -1;
            T[i].p = i;
        }
        sort (T, T+N);
        for (i=0;i<N;i++) {
            P[stp][T[i].p] = (i>0 && T[i].e[0] == T[i-1].e[0] && T[i].e[1] == T[i-1].e[1]) ? P[stp][T[i-1].p] : i;
        }
    }

    int pp = 0;

    for (i=1; i<N; i++) {
        if (T[i].p == 0) pp = i;
        int x = T[i-1].p, y = T[i].p;
        for (j = stp-1; j >= 0 && x < N && y < N; j--) {
            if (P[j][x] == P[j][y])
                x += (1<<j), y += (1<<j), D[i] += (1<<j);
        }
    }

    for (i=pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i = pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i-1].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    ans.PB (MP(N,1));

    cout << ans.SZ << endl;
    sort (ans.begin(), ans.end());

    for (i=0; i<ans.SZ; i++)
        cout << ans[i].X << " " << ans[i].Y << endl;

    return 0;
}


/*
ID: Labib666
LANG: C++
Contest: Codeforces R246
Task: 4
*/

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define VI vector <int>
#define VLL vector <LL>
#define PQI priority_queue <int>
#define PQLL priority_queue <LL>
#define QI queue <int>
#define QLL queue <LL>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define SZ size()
#define INF 1000000007
#define LINF 1000000000000000007
#define PI 2*asin(1)
#define EPS 1e-9

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     ((A).begin(), (A).end())
#define MEM(A,V)   memset (A, (V), sizeof A)

int gcd (int a, int b){return (b > a) ? gcd (b,a) : (b == 0) ? a : gcd (b, a%b);}
int bitcount (int a) {return (a != 0) ? bitcount(a & (a-1)) + 1 : 0;}
LL bigmod (LL num, LL pow, LL prime) {
    if (pow == 0ll) return 1ll;
    LL ans = bigmod(num, pow/2ll, prime); ans = (ans*ans)%prime;
    if (pow%2ll) ans = (ans*num)%prime; return ans;
}

#define MAXN 100005
#define MAXLG 20

struct Data {
    int    e[2], p;
    bool operator < (const Data &d) const {
        return make_pair(e[0], e[1]) < make_pair(d.e[0], d.e[1]);
    }
} T[MAXN];

int P[MAXLG][MAXN], D[MAXN], N, stp, cnt, i, j;
char A[MAXN];

int B[MAXN];
void U(int pos) {
    while (pos <= N) {
        B[pos]++;
        pos += pos&-pos;
    }
    return;
}
int Q (int pos) {
    int ans = 0;
    while (pos != 0) {
        ans += B[pos];
        pos -= pos&-pos;
    }
    return ans;
}

vector <PII> ans;

int main()
{
    //freopen("input.txt", "r", stdin);
    cin >> A;
    N = strlen (A);

    for (i = 0; i < N; i++)
        P[0][i] = A[i]-'A';

    for (stp = 1, cnt = 1; cnt >> 1 < N; cnt <<= 1, stp++) {
        for (i=0; i<N; i++) {
            T[i].e[0] = P[stp-1][i];
            T[i].e[1] = (i+cnt < N) ? P[stp-1][i+cnt] : -1;
            T[i].p = i;
        }
        sort (T, T+N);
        for (i=0;i<N;i++) {
            P[stp][T[i].p] = (i>0 && T[i].e[0] == T[i-1].e[0] && T[i].e[1] == T[i-1].e[1]) ? P[stp][T[i-1].p] : i;
        }
    }

    int pp = 0;

    for (i=1; i<N; i++) {
        if (T[i].p == 0) pp = i;
        int x = T[i-1].p, y = T[i].p;
        for (j = stp-1; j >= 0 && x < N && y < N; j--) {
            if (P[j][x] == P[j][y])
                x += (1<<j), y += (1<<j), D[i] += (1<<j);
        }
    }

    for (i=pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i = pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i-1].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    ans.PB (MP(N,1));

    cout << ans.SZ << endl;
    sort (ans.begin(), ans.end());

    for (i=0; i<ans.SZ; i++)
        cout << ans[i].X << " " << ans[i].Y << endl;

    return 0;
}


/*
ID: Labib666
LANG: C++
Contest: Codeforces R246
Task: 4
*/

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define VI vector <int>
#define VLL vector <LL>
#define PQI priority_queue <int>
#define PQLL priority_queue <LL>
#define QI queue <int>
#define QLL queue <LL>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define SZ size()
#define INF 1000000007
#define LINF 1000000000000000007
#define PI 2*asin(1)
#define EPS 1e-9

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     ((A).begin(), (A).end())
#define MEM(A,V)   memset (A, (V), sizeof A)

int gcd (int a, int b){return (b > a) ? gcd (b,a) : (b == 0) ? a : gcd (b, a%b);}
int bitcount (int a) {return (a != 0) ? bitcount(a & (a-1)) + 1 : 0;}
LL bigmod (LL num, LL pow, LL prime) {
    if (pow == 0ll) return 1ll;
    LL ans = bigmod(num, pow/2ll, prime); ans = (ans*ans)%prime;
    if (pow%2ll) ans = (ans*num)%prime; return ans;
}

#define MAXN 100005
#define MAXLG 18

struct Data {
    int    e[2], p;
    bool operator < (const Data &d) const {
        return make_pair(e[0], e[1]) < make_pair(d.e[0], d.e[1]);
    }
} T[MAXN];                                             //** T = Sorted suffixes

int P[MAXLG][MAXN], D[MAXN], N, stp;                   //** P = rank of suffix , D = LCP of consecutively ranked suffixes
string A;                                             //** A = given string

vector <PII> ans;
int B[MAXN];

void U(int pos) {
    while (pos <= N) {
        B[pos]++;
        pos += pos&-pos;
    }
    return;
}

int Q (int pos) {
    int ans = 0;
    while (pos != 0) {
        ans += B[pos];
        pos -= pos&-pos;
    }
    return ans;
}

void SuffixArray(string A) {
    int cnt, i, j;

    for (i = 0; i < N; i++)
        P[0][i] = A[i]-'a';                            //**  <- Change in case of uppercase letters

    for (stp = 1, cnt = 1; cnt >> 1 < N; cnt <<= 1, stp++) {
        for (i=0; i<N; i++) {
            T[i].e[0] = P[stp-1][i];
            T[i].e[1] = (i+cnt < N) ? P[stp-1][i+cnt] : -1;
            T[i].p = i;
        }

        sort (T, T+N);
        for (i=0;i<N;i++) {
            P[stp][T[i].p] = (i>0 && T[i].e[0] == T[i-1].e[0] && T[i].e[1] == T[i-1].e[1]) ? P[stp][T[i-1].p] : i;
        }
    }

    return;
}

int LCP(int x, int y) {
    int ans = 0;
    for (int j = stp-1; j >= 0 && x < N && y < N; j--) {
        if (P[j][x] == P[j][y])
            x += (1<<j), y += (1<<j), ans += (1<<j);
    }
    return ans;
}

int main()
{
    int i, j, kk, pp = 0;

    cin >> A;
    N = A.size();

    SuffixArray(A);

    for (int i=1; i<N; i++) {
        int x = T[i-1].p, y = T[i].p;
        if (y == 0) pp = i;
        D[i] = LCP(x, y);
    }

    for (i=pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i = pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i-1].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    ans.PB (MP(N,1));

    cout << ans.SZ << endl;
    sort (ans.begin(), ans.end());

    for (i=0; i<ans.SZ; i++)
        cout << ans[i].X << " " << ans[i].Y << endl;

    return 0;
}


/*
ID: Labib666
LANG: C++
Contest: Codeforces R246
Task: 4
*/

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define VI vector <int>
#define VLL vector <LL>
#define PQI priority_queue <int>
#define PQLL priority_queue <LL>
#define QI queue <int>
#define QLL queue <LL>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define SZ size()
#define INF 1000000007
#define LINF 1000000000000000007
#define PI 2*asin(1)
#define EPS 1e-9

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     ((A).begin(), (A).end())
#define MEM(A,V)   memset (A, (V), sizeof A)

int gcd (int a, int b){return (b > a) ? gcd (b,a) : (b == 0) ? a : gcd (b, a%b);}
int bitcount (int a) {return (a != 0) ? bitcount(a & (a-1)) + 1 : 0;}
LL bigmod (LL num, LL pow, LL prime) {
    if (pow == 0ll) return 1ll;
    LL ans = bigmod(num, pow/2ll, prime); ans = (ans*ans)%prime;
    if (pow%2ll) ans = (ans*num)%prime; return ans;
}

#define MAXN 100005
#define MAXLG 20

struct Data {
    int    e[2], p;
    bool operator < (const Data &d) const {
        return make_pair(e[0], e[1]) < make_pair(d.e[0], d.e[1]);
    }
} T[MAXN];

int P[MAXLG][MAXN], D[MAXN], N, stp, cnt, i, j;
char A[MAXN];

int B[MAXN];
void U(int pos) {
    while (pos <= N) {
        B[pos]++;
        pos += pos&-pos;
    }
    return;
}
int Q (int pos) {
    int ans = 0;
    while (pos != 0) {
        ans += B[pos];
        pos -= pos&-pos;
    }
    return ans;
}

vector <PII> ans;

int main()
{
    //freopen("input.txt", "r", stdin);
    cin >> A;
    N = strlen (A);

    for (i = 0; i < N; i++)
        P[0][i] = A[i]-'A';

    for (stp = 1, cnt = 1; cnt >> 1 < N; cnt <<= 1, stp++) {
        for (i=0; i<N; i++) {
            T[i].e[0] = P[stp-1][i];
            T[i].e[1] = (i+cnt < N) ? P[stp-1][i+cnt] : -1;
            T[i].p = i;
        }
        sort (T, T+N);
        for (i=0;i<N;i++) {
            P[stp][T[i].p] = (i>0 && T[i].e[0] == T[i-1].e[0] && T[i].e[1] == T[i-1].e[1]) ? P[stp][T[i-1].p] : i;
        }
    }

    /*string BB = A;
    FOR(ii,0,N) {
        cout << BB.substr(T[ii].p) << endl;;
    }*/

    int pp = 0;

    for (i=1; i<N; i++) {
        if (T[i].p == 0) pp = i;
        int x = T[i-1].p, y = T[i].p;
        for (j = stp-1; j >= 0 && x < N && y < N; j--) {
            if (P[j][x] == P[j][y])
                x += (1<<j), y += (1<<j), D[i] += (1<<j);
        }
    }

    for (i=pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }
    if (pp < N-1) {
        for (i=pp+1, j = D[i]; i < N; i++) {
            j = min (j, D[i]);
            if (j <= 0) break;
            U(j);
        }
    }

    for (i = pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i-1].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    if (pp < N-1) {
        for (i=pp+1, j = D[i]; i < N; i++) {
            j = min (j, D[i]);
            if (j <= 0) break;

            int kk = N-T[i].p;
            if (kk == j) {
                ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
            }
        }
    }

    ans.PB (MP(N,1));

    cout << ans.SZ << endl;
    sort (ans.begin(), ans.end());

    for (i=0; i<ans.SZ; i++)
        cout << ans[i].X << " " << ans[i].Y << endl;

    return 0;
}


/*
ID: Labib666
LANG: C++
Contest: Codeforces R246
Task: 4
*/

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define VI vector <int>
#define VLL vector <LL>
#define PQI priority_queue <int>
#define PQLL priority_queue <LL>
#define QI queue <int>
#define QLL queue <LL>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define SZ size()
#define INF 1000000007
#define LINF 1000000000000000007
#define PI 2*asin(1)
#define EPS 1e-9

#define FOR(I,A,B) for(int I = (A); I < (B); ++I)
#define REP(I,N)   FOR(I,0,N)
#define ALL(A)     ((A).begin(), (A).end())
#define MEM(A,V)   memset (A, (V), sizeof A)

int gcd (int a, int b){return (b > a) ? gcd (b,a) : (b == 0) ? a : gcd (b, a%b);}
int bitcount (int a) {return (a != 0) ? bitcount(a & (a-1)) + 1 : 0;}
LL bigmod (LL num, LL pow, LL prime) {
    if (pow == 0ll) return 1ll;
    LL ans = bigmod(num, pow/2ll, prime); ans = (ans*ans)%prime;
    if (pow%2ll) ans = (ans*num)%prime; return ans;
}

#define MAXN 100005
#define MAXLG 20

struct Data {
    int    e[2], p;
    bool operator < (const Data &d) const {
        return make_pair(e[0], e[1]) < make_pair(d.e[0], d.e[1]);
    }
} T[MAXN];                                             //** T = Sorted suffixes

int P[MAXLG][MAXN], D[MAXN], N, stp;                   //** P = rank of suffix , D = LCP of consecutively ranked suffixes
string A;                                              //** A = given string

vector <PII> ans;
int B[MAXN];

void U(int pos) {
    while (pos <= N) {
        B[pos]++;
        pos += pos&-pos;
    }
    return;
}

int Q (int pos) {
    int ans = 0;
    while (pos != 0) {
        ans += B[pos];
        pos -= pos&-pos;
    }
    return ans;
}

void SuffixArray(string A) {
    int cnt, i, j;

    for (i = 0; i < N; i++)
        P[0][i] = A[i]-'A';                            //**  <- Change in case of uppercase letters

    for (stp = 1, cnt = 1; cnt >> 1 < N; cnt <<= 1, stp++) {
        for (i=0; i<N; i++) {
            T[i].e[0] = P[stp-1][i];
            T[i].e[1] = (i+cnt < N) ? P[stp-1][i+cnt] : -1;
            T[i].p = i;
        }

        sort (T, T+N);
        for (i=0;i<N;i++) {
            P[stp][T[i].p] = (i>0 && T[i].e[0] == T[i-1].e[0] && T[i].e[1] == T[i-1].e[1]) ? P[stp][T[i-1].p] : i;
        }
    }

    return;
}

int LCP(int x, int y) {
    int ans = 0;
    for (int j = stp-1; j >= 0 && x < N && y < N; j--) {
        if (P[j][x] == P[j][y])
            x += (1<<j), y += (1<<j), ans += (1<<j);
    }
    return ans;
}

int main()
{
    int i, j, kk, pp = 0;

    cin >> A;
    N = A.size();

    SuffixArray(A);

    for (int i=1; i<N; i++) {
        int x = T[i-1].p, y = T[i].p;
        if (y == 0) pp = i;
        D[i] = LCP(x, y);
    }

    for (i=pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;
        U(j);
    }

    for (i = pp, j = D[i]; i > 0; i--) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i-1].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    for (i=pp+1, j = D[i]; i < N; i++) {
        j = min (j, D[i]);
        if (j <= 0) break;

        int kk = N-T[i].p;
        if (kk == j) {
            ans.PB (MP (kk, Q(N)-Q(kk-1)+1));
        }
    }

    ans.PB (MP(N,1));

    cout << ans.SZ << endl;
    sort (ans.begin(), ans.end());

    for (i=0; i<ans.SZ; i++)
        cout << ans[i].X << " " << ans[i].Y << endl;

    return 0;
}