//BISMILLAHIRRAHMANIRRAHIM
/*
manus tar shopner soman boro
all my suceesses are dedicated to my parents
Author :: Shakil Ahmed
.............AUST_CSE27.........
prob ::
Type ::
verdict::
*/
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define pi acos(-1.0)
#define ff first
#define ss second
#define re return
#define QI queue<int>
#define SI stack<int>
#define SZ(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define ms(a,b) memset((a),(b),sizeof(a))
#define G() getchar()
#define MAX3(a,b,c) max(a,max(b,c))
#define II ( { int a ; read(a) ; a; } )
#define LL ( { Long a ; read(a) ; a; } )
#define DD ({double a; scanf("%lf", &a); a;})
double const EPS=3e-8;
using namespace std;
#define FI freopen ("input.txt", "r", stdin)
#define FO freopen ("output.txt", "w", stdout)
typedef long long Long;
typedef long long int64;
typedef unsigned long long ull;
typedef vector<int> vi ;
typedef set<int> si;
typedef vector<Long>vl;
typedef pair<int,int>pii;
typedef pair<string,int>psi;
typedef pair<Long,Long>pll;
typedef pair<double,double>pdd;
typedef vector<pii> vpii;
// For loop
#define forab(i, a, b) for (__typeof (b) i = (a) ; i <= b ; ++i)
#define rep(i, n) forab (i, 0, (n) - 1)
#define For(i, n) forab (i, 1, n)
#define rofba(i, a, b) for (__typeof (b)i = (b) ; i >= a ; --i)
#define per(i, n) rofba (i, 0, (n) - 1)
#define rof(i, n) rofba (i, 1, n)
#define forstl(i, s) for (__typeof ((s).end ()) i = (s).begin (); i != (s).end (); ++i)
template< class T > T gcd(T a, T b) { return (b != 0 ? gcd<T>(b, a%b) : a); }
template< class T > T lcm(T a, T b) { return (a / gcd<T>(a, b) * b); }
//Fast Reader
template<class T>inline bool read(T &x){int c=getchar();int sgn=1;while(~c&&c<'0'||c>'9'){if(c=='-')sgn=-1;c=getchar();}for(x=0;~c&&'0'<=c&&c<='9';c=getchar())x=x*10+c-'0'; x*=sgn; return ~c;}
//int dx[]={1,0,-1,0};int dy[]={0,1,0,-1}; //4 Direction
//int dx[]={1,1,0,-1,-1,-1,0,1};int dy[]={0,1,1,1,0,-1,-1,-1};//8 direction
//int dx[]={2,1,-1,-2,-2,-1,1,2};int dy[]={1,2,2,1,-1,-2,-2,-1};//Knight Direction
//int dx[]={2,1,-1,-2,-1,1};int dy[]={0,1,1,0,-1,-1}; //Hexagonal Direction
/* ************************************** My code start here ****************************************** */
const int NX = 1e5 + 10 ;
int Z[NX] , sz , CumSum[NX] ;
char inp[NX];
void Z_algorithm()
{
sz = strlen( inp );
Z[0] = sz ; // always ;
int i , l , r ;
for ( i = 1 , l = 0 , r = 0 ; i < sz ; i++ )
{
if( i <= r ) Z[i] = min( r - i + 1 , Z[i-l] );
while( i + Z[i] < sz && inp[Z[i]] == inp[ i + Z[i]] ) ++Z[i];
if( i + Z[i] - 1 > r ) // need to update r
{
l = i ;
r = i + Z[i] - 1 ;
}
}
}
int main()
{
// I will always use scanf and printf
// May be i won't be a good programmer but i will be a good human being
//cout << Num( 72 ) << endl ;
scanf("%s",inp);
Z_algorithm();
vector < pii > ans ;
int i ;
// CumSum[sz]++;
for ( i = 0 ; i < sz ; i++ )
{
if( Z[i] ) {
CumSum[1]++;
CumSum[Z[i] + 1]--;
}
}
for ( i = 1 ; i <= sz ; i++ ) CumSum[i] += CumSum[i-1];
for ( i = sz - 1 ; i >= 0 ; i-- )
{
if( Z[i] == sz - i ) // suffix matches
{
ans.pb( mp( sz - i , CumSum[Z[i]] ) );
}
}
sz = ans.size();
cout << sz << endl ;
rep( i , sz ) cout << ans[i].ff << " " << ans[i].ss << endl ;
return 0;
}
Ly9CSVNNSUxMQUhJUlJBSE1BTklSUkFISU0KLyoKIG1hbnVzIHRhciBzaG9wbmVyIHNvbWFuIGJvcm8KIGFsbCBteSBzdWNlZXNzZXMgYXJlIGRlZGljYXRlZCB0byBteSBwYXJlbnRzCiBBdXRob3IgOjogU2hha2lsIEFobWVkCi4uLi4uLi4uLi4uLi5BVVNUX0NTRTI3Li4uLi4uLi4uCiBwcm9iICAgOjoKIFR5cGUgICA6OgogdmVyZGljdDo6CiAqLwoKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNkZWZpbmUgcGIgcHVzaF9iYWNrCiNkZWZpbmUgbXAgbWFrZV9wYWlyCiNkZWZpbmUgcGkgYWNvcygtMS4wKQojZGVmaW5lIGZmIGZpcnN0CiNkZWZpbmUgc3Mgc2Vjb25kCiNkZWZpbmUgcmUgcmV0dXJuCiNkZWZpbmUgUUkgcXVldWU8aW50PgojZGVmaW5lIFNJIHN0YWNrPGludD4KI2RlZmluZSBTWih4KSAoKGludCkgKHgpLnNpemUoKSkKI2RlZmluZSBhbGwoeCkgKHgpLmJlZ2luKCksICh4KS5lbmQoKQojZGVmaW5lIHNxcih4KSAoKHgpICogKHgpKQojZGVmaW5lIG1zKGEsYikgbWVtc2V0KChhKSwoYiksc2l6ZW9mKGEpKQojZGVmaW5lIEcoKSBnZXRjaGFyKCkKI2RlZmluZSBNQVgzKGEsYixjKSBtYXgoYSxtYXgoYixjKSkKI2RlZmluZSBJSSAoIHsgaW50IGEgOyByZWFkKGEpIDsgYTsgfSApCiNkZWZpbmUgTEwgKCB7IExvbmcgYSA7IHJlYWQoYSkgOyBhOyB9ICkKI2RlZmluZSBERCAoe2RvdWJsZSBhOyBzY2FuZigiJWxmIiwgJmEpOyBhO30pCgpkb3VibGUgY29uc3QgRVBTPTNlLTg7CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgojZGVmaW5lIEZJIGZyZW9wZW4gKCJpbnB1dC50eHQiLCAiciIsIHN0ZGluKQojZGVmaW5lIEZPIGZyZW9wZW4gKCJvdXRwdXQudHh0IiwgInciLCBzdGRvdXQpCgp0eXBlZGVmIGxvbmcgbG9uZyBMb25nOwp0eXBlZGVmIGxvbmcgbG9uZyBpbnQ2NDsKdHlwZWRlZiB1bnNpZ25lZCBsb25nIGxvbmcgdWxsOwp0eXBlZGVmIHZlY3RvcjxpbnQ+IHZpIDsKdHlwZWRlZiBzZXQ8aW50PiBzaTsKdHlwZWRlZiB2ZWN0b3I8TG9uZz52bDsKdHlwZWRlZiBwYWlyPGludCxpbnQ+cGlpOwp0eXBlZGVmIHBhaXI8c3RyaW5nLGludD5wc2k7CnR5cGVkZWYgcGFpcjxMb25nLExvbmc+cGxsOwp0eXBlZGVmIHBhaXI8ZG91YmxlLGRvdWJsZT5wZGQ7CnR5cGVkZWYgdmVjdG9yPHBpaT4gdnBpaTsKCi8vIEZvciBsb29wCgojZGVmaW5lIGZvcmFiKGksIGEsIGIpCWZvciAoX190eXBlb2YgKGIpIGkgPSAoYSkgOyBpIDw9IGIgOyArK2kpCiNkZWZpbmUgcmVwKGksIG4pCQlmb3JhYiAoaSwgMCwgKG4pIC0gMSkKI2RlZmluZSBGb3IoaSwgbikJCWZvcmFiIChpLCAxLCBuKQojZGVmaW5lIHJvZmJhKGksIGEsIGIpCWZvciAoX190eXBlb2YgKGIpaSA9IChiKSA7IGkgPj0gYSA7IC0taSkKI2RlZmluZSBwZXIoaSwgbikJCXJvZmJhIChpLCAwLCAobikgLSAxKQojZGVmaW5lIHJvZihpLCBuKQkJcm9mYmEgKGksIDEsIG4pCiNkZWZpbmUgZm9yc3RsKGksIHMpCWZvciAoX190eXBlb2YgKChzKS5lbmQgKCkpIGkgPSAocykuYmVnaW4gKCk7IGkgIT0gKHMpLmVuZCAoKTsgKytpKQoKdGVtcGxhdGU8IGNsYXNzIFQgPiBUIGdjZChUIGEsIFQgYikgeyByZXR1cm4gKGIgIT0gMCA/IGdjZDxUPihiLCBhJWIpIDogYSk7IH0KdGVtcGxhdGU8IGNsYXNzIFQgPiBUIGxjbShUIGEsIFQgYikgeyByZXR1cm4gKGEgLyBnY2Q8VD4oYSwgYikgKiBiKTsgfQoKLy9GYXN0IFJlYWRlcgp0ZW1wbGF0ZTxjbGFzcyBUPmlubGluZSBib29sIHJlYWQoVCAmeCl7aW50IGM9Z2V0Y2hhcigpO2ludCBzZ249MTt3aGlsZSh+YyYmYzwnMCd8fGM+JzknKXtpZihjPT0nLScpc2duPS0xO2M9Z2V0Y2hhcigpO31mb3IoeD0wO35jJiYnMCc8PWMmJmM8PSc5JztjPWdldGNoYXIoKSl4PXgqMTArYy0nMCc7IHgqPXNnbjsgcmV0dXJuIH5jO30KCi8vaW50IGR4W109ezEsMCwtMSwwfTtpbnQgZHlbXT17MCwxLDAsLTF9OyAvLzQgRGlyZWN0aW9uCi8vaW50IGR4W109ezEsMSwwLC0xLC0xLC0xLDAsMX07aW50IGR5W109ezAsMSwxLDEsMCwtMSwtMSwtMX07Ly84IGRpcmVjdGlvbgovL2ludCBkeFtdPXsyLDEsLTEsLTIsLTIsLTEsMSwyfTtpbnQgZHlbXT17MSwyLDIsMSwtMSwtMiwtMiwtMX07Ly9LbmlnaHQgRGlyZWN0aW9uCi8vaW50IGR4W109ezIsMSwtMSwtMiwtMSwxfTtpbnQgZHlbXT17MCwxLDEsMCwtMSwtMX07IC8vSGV4YWdvbmFsIERpcmVjdGlvbgoKLyogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogIE15IGNvZGUgc3RhcnQgaGVyZSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi8KCmNvbnN0IGludCBOWCA9IDFlNSArIDEwIDsKaW50IFpbTlhdICwgc3ogLCBDdW1TdW1bTlhdIDsKY2hhciBpbnBbTlhdOwp2b2lkIFpfYWxnb3JpdGhtKCkKewogICAgc3ogPSBzdHJsZW4oIGlucCApOwogICAgWlswXSA9IHN6IDsgLy8gYWx3YXlzIDsKICAgIGludCBpICwgbCAsIHIgOwogICAgZm9yICggaSA9IDEgLCBsID0gMCAsIHIgPSAwIDsgaSA8IHN6IDsgaSsrICkKICAgIHsKICAgICAgICBpZiggaSA8PSByICkgWltpXSA9IG1pbiggciAtIGkgKyAxICwgWltpLWxdICk7CiAgICAgICAgd2hpbGUoIGkgKyBaW2ldIDwgc3ogJiYgaW5wW1pbaV1dID09IGlucFsgaSArIFpbaV1dICkgKytaW2ldOwogICAgICAgIGlmKCBpICsgWltpXSAtIDEgPiByICkgLy8gbmVlZCB0byB1cGRhdGUgcgogICAgICAgIHsKICAgICAgICAgICAgbCA9IGkgOwogICAgICAgICAgICByID0gaSArIFpbaV0gLSAxIDsKICAgICAgICB9CiAgICB9Cn0KCmludCBtYWluKCkKewogICAvLyBJIHdpbGwgYWx3YXlzIHVzZSBzY2FuZiBhbmQgcHJpbnRmCiAgIC8vIE1heSBiZSBpIHdvbid0IGJlIGEgZ29vZCBwcm9ncmFtbWVyIGJ1dCBpIHdpbGwgYmUgYSBnb29kIGh1bWFuIGJlaW5nCiAgLy9jb3V0IDw8IE51bSggNzIgKSA8PCBlbmRsIDsKCiAgICBzY2FuZigiJXMiLGlucCk7CiAgICBaX2FsZ29yaXRobSgpOwogICAgdmVjdG9yIDwgcGlpID4gYW5zIDsKICAgIGludCBpIDsKICAgLy8gQ3VtU3VtW3N6XSsrOwogICAgZm9yICggaSA9IDAgOyBpIDwgc3ogOyBpKysgKQogICAgewogICAgICAgIGlmKCBaW2ldICkgewogICAgICAgIEN1bVN1bVsxXSsrOwogICAgICAgIEN1bVN1bVtaW2ldICsgMV0tLTsKICAgICAgICB9CiAgICB9CiAgICBmb3IgKCBpID0gMSA7IGkgPD0gc3ogOyBpKysgKSBDdW1TdW1baV0gKz0gQ3VtU3VtW2ktMV07CiAgICBmb3IgKCBpID0gc3ogLSAxIDsgaSA+PSAwIDsgaS0tICkKICAgIHsKICAgICAgICBpZiggWltpXSA9PSBzeiAtIGkgKSAvLyBzdWZmaXggbWF0Y2hlcwogICAgICAgIHsKICAgICAgICAgICAgYW5zLnBiKCBtcCggc3ogLSBpICwgQ3VtU3VtW1pbaV1dICkgICk7CiAgICAgICAgfQogICAgfQogICAgc3ogPSBhbnMuc2l6ZSgpOwogICAgY291dCA8PCBzeiA8PCBlbmRsIDsKICAgIHJlcCggaSAsIHN6ICkgY291dCA8PCBhbnNbaV0uZmYgPDwgIiAiIDw8IGFuc1tpXS5zcyA8PCBlbmRsIDsKCiAgICByZXR1cm4gMDsKfQ==