#include <bits/stdc++.h>
#define ll long long
#define all(a) (a).begin(), (a).end()
#define dbg_line(x) cout << (x) << '\n'
#define dbg(x) cout << x << " "
using namespace std;
// <--> Report constants <-->
typedef pair<int, int> pii;
const int max_n = 1e5 + 5;
const ll inf = 1e9;
const ll m_inf = -1e9;
const ll mod = 1e9 + 7;
const int base = 32;
// <--> Report variables <-->
ll pref[max_n];
ll mult[max_n];
// <--> Main Code is Here <-->
void buildHash(string s){
pref[0] = 0;
mult[0] = 1;
int n = (int)s.size();
for (int i = 1; i <= n; i++){
pref[i] = (pref[i - 1] * base + s[i - 1] - 'a' + 1) % mod;
mult[i] = (mult[i - 1] * base) % mod;
}
}
// ll getHashString(string s){
// ll res = 0;
// for (char c : s){
// res = (res * base + c - 'a' + 1) % mod;
// }
// return res;
// }
ll getHash(int l, int r){
return (pref[r] - (pref[l - 1] * mult[r - l + 1]) % mod + mod) % mod;
}
void setIO(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
}
void call_file(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
}
int main(){
setIO();
call_file();
string s;
cin >> s;
buildHash(s);
vector<int> tmp;
for (int i = 1; i <= (int)s.size(); i++){
if (getHash(1, i) == getHash(s.size() - i + 1, s.size())){
tmp.push_back(i);
}
}
cout << (int)tmp.size() << '\n';
vector<pii> v;
for (int x : tmp){
int l = 1;
int cnt = 0;
int hashRes = getHash(1, x);
for (int r = x; r <= s.size(); r++){
if (getHash(l, r) == hashRes){
cnt++;
}
++l;
}
v.push_back({x, cnt});
}
for (pii x : v){
cout << x.first << " " << x.second << '\n';
}
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNkZWZpbmUgbGwgbG9uZyBsb25nCiNkZWZpbmUgYWxsKGEpIChhKS5iZWdpbigpLCAoYSkuZW5kKCkKI2RlZmluZSBkYmdfbGluZSh4KSBjb3V0IDw8ICh4KSA8PCAnXG4nCiNkZWZpbmUgZGJnKHgpIGNvdXQgPDwgeCA8PCAiICIKCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyA8LS0+IFJlcG9ydCBjb25zdGFudHMgPC0tPgoKdHlwZWRlZiBwYWlyPGludCwgaW50PiBwaWk7CmNvbnN0IGludCBtYXhfbiA9IDFlNSArIDU7CmNvbnN0IGxsIGluZiA9IDFlOTsKY29uc3QgbGwgbV9pbmYgPSAtMWU5Owpjb25zdCBsbCBtb2QgPSAxZTkgKyA3Owpjb25zdCBpbnQgYmFzZSA9IDMyOwoKLy8gPC0tPiBSZXBvcnQgdmFyaWFibGVzIDwtLT4KCmxsIHByZWZbbWF4X25dOwpsbCBtdWx0W21heF9uXTsKCi8vIDwtLT4gTWFpbiBDb2RlIGlzIEhlcmUgPC0tPgoKdm9pZCBidWlsZEhhc2goc3RyaW5nIHMpewogICAgcHJlZlswXSA9IDA7CiAgICBtdWx0WzBdID0gMTsKICAgIGludCBuID0gKGludClzLnNpemUoKTsKICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IG47IGkrKyl7CiAgICAgICAgcHJlZltpXSA9IChwcmVmW2kgLSAxXSAqIGJhc2UgKyBzW2kgLSAxXSAtICdhJyArIDEpICUgbW9kOwogICAgICAgIG11bHRbaV0gPSAobXVsdFtpIC0gMV0gKiBiYXNlKSAlIG1vZDsKICAgIH0KfQoKLy8gbGwgZ2V0SGFzaFN0cmluZyhzdHJpbmcgcyl7Ci8vICAgICBsbCByZXMgPSAwOwovLyAgICAgZm9yIChjaGFyIGMgOiBzKXsKLy8gICAgICAgICByZXMgPSAocmVzICogYmFzZSArIGMgLSAnYScgKyAxKSAlIG1vZDsKLy8gICAgIH0KLy8gICAgIHJldHVybiByZXM7Ci8vIH0KCmxsIGdldEhhc2goaW50IGwsIGludCByKXsKICAgIHJldHVybiAocHJlZltyXSAtIChwcmVmW2wgLSAxXSAqIG11bHRbciAtIGwgKyAxXSkgJSBtb2QgKyBtb2QpICUgbW9kOwp9Cgp2b2lkIHNldElPKCl7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGNpbi50aWUoTlVMTCk7CiAgICBjb3V0LnRpZShOVUxMKTsKfQoKdm9pZCBjYWxsX2ZpbGUoKXsKICAgIGZyZW9wZW4oImlucHV0LnR4dCIsInIiLHN0ZGluKTsKICAgIGZyZW9wZW4oIm91dHB1dC50eHQiLCJ3IixzdGRvdXQpOwp9CgppbnQgbWFpbigpewogICAgc2V0SU8oKTsKICAgIGNhbGxfZmlsZSgpOwogICAgc3RyaW5nIHM7CiAgICBjaW4gPj4gczsKICAgIGJ1aWxkSGFzaChzKTsKICAgIHZlY3RvcjxpbnQ+IHRtcDsKICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IChpbnQpcy5zaXplKCk7IGkrKyl7CiAgICAgICAgaWYgKGdldEhhc2goMSwgaSkgPT0gZ2V0SGFzaChzLnNpemUoKSAtIGkgKyAxLCBzLnNpemUoKSkpewogICAgICAgICAgICB0bXAucHVzaF9iYWNrKGkpOwogICAgICAgIH0KICAgIH0KICAgIGNvdXQgPDwgKGludCl0bXAuc2l6ZSgpIDw8ICdcbic7CiAgICB2ZWN0b3I8cGlpPiB2OwogICAgZm9yIChpbnQgeCA6IHRtcCl7CiAgICAgICAgaW50IGwgPSAxOwogICAgICAgIGludCBjbnQgPSAwOwogICAgICAgIGludCBoYXNoUmVzID0gZ2V0SGFzaCgxLCB4KTsKICAgICAgICBmb3IgKGludCByID0geDsgciA8PSBzLnNpemUoKTsgcisrKXsKICAgICAgICAgICAgaWYgKGdldEhhc2gobCwgcikgPT0gaGFzaFJlcyl7CiAgICAgICAgICAgICAgICBjbnQrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICArK2w7CiAgICAgICAgfQogICAgICAgIHYucHVzaF9iYWNrKHt4LCBjbnR9KTsKICAgIH0KICAgIGZvciAocGlpIHggOiB2KXsKICAgICAgICBjb3V0IDw8IHguZmlyc3QgPDwgIiAiIDw8IHguc2Vjb25kIDw8ICdcbic7CiAgICB9Cn0K