#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    zs[0] = n;
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    map <int, int> h;
    set <int> st;
    string s;
    cin >> s;

    zz = z(s);

    for (int i = zz[0]-1; i >= 0; i--)
    {
        if (zz[i] == zz[0]-i) st.insert(zz[i]);
        h[zz[i]]++;
    }

    if (h.size() > 2)
    {
        auto it = h.end();
        --it;
        --it;
        do
        {
            (--it)->second += (++it)->second;
            --it;
        } while (it != h.begin());
        (--it)->second += (++it)->second;
    }

    cout << st.size() << endl;
    for (auto c : st)
        cout << c << " " << h[c] << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using Node = map<char, int>;
using Trie = vector<Node>;

Trie build_online(const string& s)
{
    int next = 0, deepest = 0;
    string S = s + '#';
    vector<int> suf {-1};
    Trie trie(1);
    for (size_t i = 0; i < S.length(); ++i)
    {
        char c = S[i];
        int u = deepest;
        while (u >= 0)
        {
            auto it = trie[u].find(c);
            if (it == trie[u].end())
            {
                trie.push_back({ });
                trie[u][c] = ++next;
                suf.push_back(0);
                if (u != deepest)
                    suf[next-1] = next;
                else deepest = next;
            }
            else
            {
                suf[next] = it->second;
                break;
            }
            u = suf[u];
        }
    }
    return trie;
}

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

vector <int> strong_borders(const string& P)
{
    int m = P.size(), t = -1;
    vector<int> bs(m + 1, -1);
    for (int j = 1; j <= m; ++j)
    {
        while (t > -1 and P[t] != P[j - 1])
            t = bs[t];
        ++t;
        bs[j] = (j == m or P[t] != P[j]) ? t : bs[t];
    }
    return bs;
}

int main()
{
    ios::sync_with_stdio(false);

    int n;
    vector <int> bs, zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    bs = strong_borders(s);
    n = bs[bs.size()-1];
    zz = z(s.substr(0, n)+"$"+s);

    for (size_t i = n; i < zz.size(); i++)
        if (zz[i] <= n && zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(pair<int, int>(c.first, c.second));

    if (v.size() > 1)
        for (int i = v.size()-2; i >= 0; i--)
            v[i].second += v[i+1].second;

    for (auto c : v) cout << c.first << " " << c.second << endl;
    cout << s.length() << " " << 1 << endl;
    // for (auto c : zz) cout << c << " ";
    // cout << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    zz = z(s);
    zz[0]=(int)s.size();

    for (int i = 0; i < zz[0]; i++)
        if (zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(make_pair(c.first, c.second));

    for (int i = v.size()-2; i >= 0; i--)
        v[i].second += v[i+1].second;

    cout << v.size() << endl;
    for (auto c : v)
        cout << c.first << " " << c.second << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using Node = map<char, int>;
using Trie = vector<Node>;

Trie build_online(const string& s)
{
    int next = 0, deepest = 0;
    string S = s + '#';
    vector<int> suf {-1};
    Trie trie(1);
    for (size_t i = 0; i < S.length(); ++i)
    {
        char c = S[i];
        int u = deepest;
        while (u >= 0)
        {
            auto it = trie[u].find(c);
            if (it == trie[u].end())
            {
                trie.push_back({ });
                trie[u][c] = ++next;
                suf.push_back(0);
                if (u != deepest)
                    suf[next-1] = next;
                else deepest = next;
            }
            else
            {
                suf[next] = it->second;
                break;
            }
            u = suf[u];
        }
    }
    return trie;
}

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

vector <int> strong_borders(const string& P)
{
    int m = P.size(), t = -1;
    vector<int> bs(m + 1, -1);
    for (int j = 1; j <= m; ++j)
    {
        while (t > -1 and P[t] != P[j - 1])
            t = bs[t];
        ++t;
        bs[j] = (j == m or P[t] != P[j]) ? t : bs[t];
    }
    return bs;
}

int main()
{
    ios::sync_with_stdio(false);

    int n;
    vector <int> bs, zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    bs = strong_borders(s);
    n = bs[bs.size()-1];
    zz = z(s.substr(0, n)+"&"+s);

    for (size_t i = n; i < zz.size(); i++)
        if (zz[i] <= n && zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(pair<int, int>(c.first, c.second));

    if (v.size() > 1)
        for (int i = v.size()-2; i >= 0; i--)
            v[i].second += v[i+1].second;

    for (auto c : v) cout << c.first << " " << c.second << endl;
    cout << s.length() << " " << 1 << endl;
    // for (auto c : zz) cout << c << " ";
    // cout << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using Node = map<char, int>;
using Trie = vector<Node>;

Trie build_online(const string& s)
{
    int next = 0, deepest = 0;
    string S = s + '#';
    vector<int> suf {-1};
    Trie trie(1);
    for (size_t i = 0; i < S.length(); ++i)
    {
        char c = S[i];
        int u = deepest;
        while (u >= 0)
        {
            auto it = trie[u].find(c);
            if (it == trie[u].end())
            {
                trie.push_back({ });
                trie[u][c] = ++next;
                suf.push_back(0);
                if (u != deepest)
                    suf[next-1] = next;
                else deepest = next;
            }
            else
            {
                suf[next] = it->second;
                break;
            }
            u = suf[u];
        }
    }
    return trie;
}

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

vector <int> strong_borders(const string& P)
{
    int m = P.size(), t = -1;
    vector<int> bs(m + 1, -1);
    for (int j = 1; j <= m; ++j)
    {
        while (t > -1 and P[t] != P[j - 1])
            t = bs[t];
        ++t;
        bs[j] = (j == m or P[t] != P[j]) ? t : bs[t];
    }
    return bs;
}

int main()
{
    ios::sync_with_stdio(false);

    int n;
    vector <int> bs, zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    bs = strong_borders(s);
    n = bs[bs.size()-1];
    zz = z(s.substr(0, n)+"&&&&"+s);

    for (size_t i = n; i < zz.size(); i++)
        if (zz[i] <= n && zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(make_pair(c.first, c.second));

    if (v.size() > 1)
        for (int i = v.size()-2; i >= 0; i--)
            v[i].second += v[i+1].second;
    cout << v.size()+1 << endl;
    for (auto c : v) cout << c.first << " " << c.second << endl;
    cout << s.length() << " " << 1 << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using Node = map<char, int>;
using Trie = vector<Node>;

Trie build_online(const string& s)
{
    int next = 0, deepest = 0;
    string S = s + '#';
    vector<int> suf {-1};
    Trie trie(1);
    for (size_t i = 0; i < S.length(); ++i)
    {
        char c = S[i];
        int u = deepest;
        while (u >= 0)
        {
            auto it = trie[u].find(c);
            if (it == trie[u].end())
            {
                trie.push_back({ });
                trie[u][c] = ++next;
                suf.push_back(0);
                if (u != deepest)
                    suf[next-1] = next;
                else deepest = next;
            }
            else
            {
                suf[next] = it->second;
                break;
            }
            u = suf[u];
        }
    }
    return trie;
}

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

vector <int> strong_borders(const string& P)
{
    int m = P.size(), t = -1;
    vector<int> bs(m + 1, -1);
    for (int j = 1; j <= m; ++j)
    {
        while (t > -1 and P[t] != P[j - 1])
            t = bs[t];
        ++t;
        bs[j] = (j == m or P[t] != P[j]) ? t : bs[t];
    }
    return bs;
}

int main()
{
    ios::sync_with_stdio(false);

    int n;
    vector <int> bs, zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    bs = strong_borders(s);
    n = bs[bs.size()-1];
    zz = z(s.substr(0, n)+"$"+s);

    for (size_t i = n; i < zz.size(); i++)
        if (zz[i] <= n && zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(pair<int, int>(c.first, c.second));

    if (v.size() > 1)
        for (int i = v.size()-2; i >= 0; i--)
            v[i].second += v[i+1].second;

    cout << v.size()+1 << endl;
    for (auto c : v) cout << c.first << " " << c.second << endl;
    cout << s.length() << " " << 1 << endl;
    // for (auto c : zz) cout << c << " ";
    // cout << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    zs[0] = n;
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    zz = z(s);

    for (int i = zz[0]-1; i >= 0; i--)
        if (zz[i] == zz[0]-i)
            h.insert(make_pair(zz[i], 0));

    for (int i = 0; i < zz[0];i++)
        if (h.find(zz[i]) != h.end())
            h[zz[i]]++;

    for (auto c : h)
        v.push_back(make_pair(c.first, c.second));

    for (int i = v.size()-2; i >= 0; i--)
        v[i].second += v[i+1].second;

    cout << v.size() << endl;
    for (auto c : v)
        cout << c.first << " " << c.second << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    zs[0] = n;
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    map <int, int> h;
    set <int> st;
    string s;
    cin >> s;

    zz = z(s);

    for (int i = zz[0]-1; i >= 0; i--)
    {
        if (zz[i] == zz[0]-i) st.insert(zz[i]);
        h[zz[i]]++;
    }

    // if (h.size() > 2)
    // {
        auto it = h.end();
        --it;
        --it;
        do
        {
            (--it)->second += (++it)->second;
            --it;
        } while (it != h.begin());
        (--it)->second += (++it)->second;
    // }

    cout << st.size() << endl;
    for (auto c : st)
        cout << c << " " << h[c] << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    zz = z(s);
    zz[0]=(int)s.size();

    for (int i = 0; i < zz[0]; i++)
        if (zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(make_pair(c.first, c.second));

    for (int i = v.size()-1; i >= 0; i--)
        v[i].second += v[i+1].second;

    cout << v.size() << endl;
    for (auto c : v)
        cout << c.first << " " << c.second << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    zs[0] = n;
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    map <int, int> h;
    set <int> st;
    string s;
    cin >> s;

    zz = z(s);

    for (int i = zz[0]-1; i >= 0; i--)
    {
        if (zz[i] == zz[0]-i) st.insert(zz[i]);
        h[zz[i]]++;
    }

    if (h.size() > 1)
    {
        auto it = h.end();
        --it;
        --it;
        if (h.size() > 2)
        {
            do
            {
                (--it)->second += (++it)->second;
                --it;
            } while (it != h.begin());
        }
        (--it)->second += (++it)->second;
    }

    cout << st.size() << endl;
    for (auto c : st)
        cout << c << " " << h[c] << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
using Node = map<char, int>;
using Trie = vector<Node>;

Trie build_online(const string& s)
{
    int next = 0, deepest = 0;
    string S = s + '#';
    vector<int> suf {-1};
    Trie trie(1);
    for (size_t i = 0; i < S.length(); ++i)
    {
        char c = S[i];
        int u = deepest;
        while (u >= 0)
        {
            auto it = trie[u].find(c);
            if (it == trie[u].end())
            {
                trie.push_back({ });
                trie[u][c] = ++next;
                suf.push_back(0);
                if (u != deepest)
                    suf[next-1] = next;
                else deepest = next;
            }
            else
            {
                suf[next] = it->second;
                break;
            }
            u = suf[u];
        }
    }
    return trie;
}

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

vector <int> strong_borders(const string& P)
{
    int m = P.size(), t = -1;
    vector<int> bs(m + 1, -1);
    for (int j = 1; j <= m; ++j)
    {
        while (t > -1 and P[t] != P[j - 1])
            t = bs[t];
        ++t;
        bs[j] = (j == m or P[t] != P[j]) ? t : bs[t];
    }
    return bs;
}

int main()
{
    ios::sync_with_stdio(false);

    int n;
    vector <int> bs, zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    bs = strong_borders(s);
    n = bs[bs.size()-1];
    zz = z(s.substr(0, n)+"&"+s);

    for (size_t i = n; i < zz.size(); i++)
        if (zz[i] <= n && zz[i]) h[zz[i]]++;

    for (auto c : h)
        v.push_back(pair<int, int>(c.first, c.second));

    if (v.size() > 1)
        for (int i = v.size()-2; i >= 0; i--)
            v[i].second += v[i+1].second;
    cout << v.size()+1 << endl;
    for (auto c : v) cout << c.first << " " << c.second << endl;
    cout << s.length() << " " << 1 << endl;
    // for (auto c : zz) cout << c << " ";
    // cout << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int> z(const string& s)
{
    int n = s.size(), l = 0, r = 0;
    vector<int> zs(n,0);
    for (int i = 1; i < n; i++)
    {
        if (i<=r)
            zs[i] = min(zs[i-l], r-i+1);
        while (zs[i]+i<n && s[zs[i]]==s[i+zs[i]])
            zs[i]++;
        if (r<i +zs[i]-1)
            l = i, r = i + zs[i] - 1;
    }
    return zs;
}

int main()
{
    ios::sync_with_stdio(false);

    vector <int> zz;
    vector <pair<int, int>> v;
    map <int, int> h;
    string s;
    cin >> s;

    zz = z(s);
    zz[0]=(int)s.size();

    for (int i = zz[0]-1; i >= 0; --i)
        if (zz[i] == zz[0]-i) h[zz[i]]++;

    for (auto c : h)
        v.push_back(make_pair(c.first, c.second));

    for (int i = v.size()-2; i >= 0; i--)
        v[i].second += v[i+1].second;

    cout << v.size() << endl;
    for (auto c : v)
        cout << c.first << " " << c.second << endl;

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)(1e5 + 5)
#define MAXM (int)(3e5 + 5)
#define fr first
#define sd second
#define MP make_pair
#define pb push_back
#define SZ(A) (int)A.size()
#define ALL(v) v.begin(), v.end()
#define M0(a) memset(a, 0, sizeof(a))
#define M1(a) memset(a, -1, sizeof(a))
#define REP(i,n) for(int i = 0; i < int(n); i++)
#define REPN(i,n,m) for(int i = m; i <= int(n); i++)
#define RREP(i,n) for(int i = int(n-1); i >= 0; i--)
#define RREPN(i, n, m) for(int i = (int)n; i >= (int)m; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int INF = int(1e8 + 7);
const ll MOD = ll(1e9 + 7);
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<pii, pii> ppii;
template<typename T, typename U> inline void AMIN(T &x, U y){ if(x > y) x = y;}
template<typename T, typename U> inline void AMAX(T &x, U y){ if(x < y) x = y;}
int Z[MAXN], LK[MAXN], SUM[MAXN];

int main() {

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        string S;
        cin >> S;
        int N = S.size();

        for(int i = 1, L = 0, R = 0; i < N; i++) {

                if(i <= R)
                        Z[i] = min(Z[i - L], R - i + 1);

                while(i + Z[i] < N && S[Z[i]] == S[i + Z[i]])
                        Z[i]++;

                if(i + Z[i] - 1 > R)
                        L = i, R = i + Z[i] - 1;
        }

        Z[0] = S.size();

        REP(i, N)
                SUM[Z[i]]++;

        REPN(i, N, 1)
                SUM[i] += SUM[i - 1];

        vector<vector<int>> ANS;
        REP(i, N)
                if(i + Z[i] == N)
                        ANS.pb({Z[i], SUM[N] - SUM[Z[i] - 1]});

        sort(ALL(ANS));
        cout << ANS.size() << endl;
        REP(i, ANS.size())
                cout << ANS[i][0] << " " << ANS[i][1] << endl;

        return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)(2e5 + 5)
#define MAXM (int)(3e5 + 5)
#define fr first
#define sd second
#define MP make_pair
#define pb push_back
#define SZ(A) (int)A.size()
#define ALL(v) v.begin(), v.end()
#define M0(a) memset(a, 0, sizeof(a))
#define M1(a) memset(a, -1, sizeof(a))
#define REP(i,n) for(int i = 0; i < int(n); i++)
#define REPN(i,n,m) for(int i = m; i <= int(n); i++)
#define RREP(i,n) for(int i = int(n-1); i >= 0; i--)
#define RREPN(i, n, m) for(int i = (int)n; i >= (int)m; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int INF = int(1e8 + 7);
const ll MOD = ll(1e9 + 7);
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<pii, pii> ppii;
template<typename T, typename U> inline void AMIN(T &x, U y){ if(x > y) x = y;}
template<typename T, typename U> inline void AMAX(T &x, U y){ if(x < y) x = y;}
int Z[MAXN], LK[MAXN], SUM[MAXN];

int main() {

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        string S;
        cin >> S;
        int N = S.size();

        for(int i = 1, L = 0, R = 0; i < N; i++) {

                if(i <= R)
                        Z[i] = min(Z[i - L], R - i + 1);

                while(i + Z[i] < N && S[Z[i]] == S[i + Z[i]])
                        Z[i]++;

                if(i + Z[i] - 1 > R)
                        L = i, R = i + Z[i] - 1;
        }

        Z[0] = S.size();
        REP(i, N)
                LK[Z[i]]++;

        RREP(i, 150001)
                SUM[i] = LK[i] + SUM[i + 1];

        vector<vector<int>> ANS;
        REP(i, N) {

                if(i + Z[i] == N)
                        ANS.pb({Z[i], SUM[Z[i]]});
        }

        sort(ALL(ANS));
        cout << ANS.size() << endl;
        REP(i, ANS.size())
                cout << ANS[i][0] << " " << ANS[i][1] << endl;
        return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)(1e5 + 5)
#define MAXM (int)(3e5 + 5)
#define fr first
#define sd second
#define MP make_pair
#define pb push_back
#define SZ(A) (int)A.size()
#define ALL(v) v.begin(), v.end()
#define M0(a) memset(a, 0, sizeof(a))
#define M1(a) memset(a, -1, sizeof(a))
#define REP(i,n) for(int i = 0; i < int(n); i++)
#define REPN(i,n,m) for(int i = m; i <= int(n); i++)
#define RREP(i,n) for(int i = int(n-1); i >= 0; i--)
#define RREPN(i, n, m) for(int i = (int)n; i >= (int)m; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int INF = int(1e8 + 7);
const ll MOD = ll(1e9 + 7);
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<pii, pii> ppii;
template<typename T, typename U> inline void AMIN(T &x, U y){ if(x > y) x = y;}
template<typename T, typename U> inline void AMAX(T &x, U y){ if(x < y) x = y;}
int LPS[MAXN], LK[MAXN];

int main() {

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        string S;
        cin >> S;

        int N = S.size();
        REPN(i, N - 1, 1) {

                int idx = LPS[i - 1];

                while(idx > 0 && S[i] != S[idx])
                        idx = LPS[idx - 1];

                if(S[i] == S[idx])
                        LPS[i] = idx + 1;
        }

        int len = LPS[N - 1];
        while(len > 0) {

                int idx = len - 1;
                if(S[N - 1] == S[idx])
                        LK[len] = 1;

                //cout << S[N - 1] << " " << S[idx] << endl;
                len--;
        }

        REPN(i, N, 1)
                if(LK[LPS[i]])
                        LK[LPS[i]]++;

        REPN(i, N, 1)
                if(LK[i] && i < LPS[N - 1])
                        LK[i]++;

        LK[N] = 1;
        vector<vector<int>> V;
        REPN(i, N, 1)
                if(LK[i])
                        V.pb({i, LK[i]});

        cout << V.size() << endl;
        REP(i, V.size())
                cout << V[i][0] << " " << V[i][1] << endl;
        return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)(1e5 + 5)
#define MAXM (int)(3e5 + 5)
#define fr first
#define sd second
#define MP make_pair
#define pb push_back
#define SZ(A) (int)A.size()
#define ALL(v) v.begin(), v.end()
#define M0(a) memset(a, 0, sizeof(a))
#define M1(a) memset(a, -1, sizeof(a))
#define REP(i,n) for(int i = 0; i < int(n); i++)
#define REPN(i,n,m) for(int i = m; i <= int(n); i++)
#define RREP(i,n) for(int i = int(n-1); i >= 0; i--)
#define RREPN(i, n, m) for(int i = (int)n; i >= (int)m; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int INF = int(1e8 + 7);
const ll MOD = ll(1e9 + 7);
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<pii, pii> ppii;
template<typename T, typename U> inline void AMIN(T &x, U y){ if(x > y) x = y;}
template<typename T, typename U> inline void AMAX(T &x, U y){ if(x < y) x = y;}
int Z[MAXN], LK[MAXN], SUM[MAXN];

int main() {

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        string S;
        cin >> S;
        int N = S.size();

        for(int i = 1, L = 0, R = 0; i < N; i++) {

                if(i <= R)
                        Z[i] = min(Z[i - L], R - i + 1);

                while(i + Z[i] < N && S[Z[i]] == S[i + Z[i]])
                        Z[i]++;

                if(i + Z[i] - 1 > R)
                        L = i, R = i + Z[i] - 1;
        }

        Z[0] = S.size();

        REP(i, N)
                if(i + Z[i] == N)
                        LK[Z[i]] = 1;

        REP(i, N)
                if(LK[Z[i]])
                        SUM[Z[i]]++;

        REPN(i, N, 1)
                SUM[i] += SUM[i - 1];

        int cnt = 0;
        REPN(i, N, 1)
                if(LK[i])
                        cnt++;

        cout << cnt << endl;
        REPN(i, N, 1)
                if(LK[i])
                        cout << i << " " << SUM[N] - SUM[i - 1] << endl;

        return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN (int)(1e5 + 5)
#define MAXM (int)(3e5 + 5)
#define fr first
#define sd second
#define MP make_pair
#define pb push_back
#define SZ(A) (int)A.size()
#define ALL(v) v.begin(), v.end()
#define M0(a) memset(a, 0, sizeof(a))
#define M1(a) memset(a, -1, sizeof(a))
#define REP(i,n) for(int i = 0; i < int(n); i++)
#define REPN(i,n,m) for(int i = m; i <= int(n); i++)
#define RREP(i,n) for(int i = int(n-1); i >= 0; i--)
#define RREPN(i, n, m) for(int i = (int)n; i >= (int)m; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
const int INF = int(1e8 + 7);
const ll MOD = ll(1e9 + 7);
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<pii, pii> ppii;
template<typename T, typename U> inline void AMIN(T &x, U y){ if(x > y) x = y;}
template<typename T, typename U> inline void AMAX(T &x, U y){ if(x < y) x = y;}
int Z[MAXN], LK[MAXN], SUM[MAXN];

int main() {

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        string S;
        cin >> S;
        int N = S.size();

        for(int i = 1, L = 0, R = 0; i < N; i++) {

                if(i <= R)
                        Z[i] = min(Z[i - 1], R - i + 1);

                while(Z[i] < N && S[Z[i]] == S[i + Z[i]])
                        Z[i]++;

                R = Z[i];
        }

        Z[0] = S.size();

        REP(i, N)
                if(i + Z[i] == N)
                        LK[Z[i]] = 1;

        REP(i, N)
                if(LK[Z[i]])
                        SUM[Z[i]]++;

        REPN(i, N, 1)
                SUM[i] += SUM[i - 1];

        int cnt = 0;
        REPN(i, N, 1)
                if(LK[i])
                        cnt++;

        cout << cnt << endl;
        REPN(i, N, 1)
                if(LK[i])
                        cout << i << " " << SUM[N] - SUM[i - 1] << endl;

        return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    set<int> sett;
    for(int i=0;i<n;i++)
    {
        if(z[i]!=0)
        sett.insert(z[i]);
    }
    z[0]=n;
    sort(z.begin(),z.end());
    int first=lower_bound(z.begin(),z.end(),1)-z.begin();
    cout<<sett.size()<<endl;
    for(auto s:sett)
    {
        int ele = n-(lower_bound(z.begin(),z.end(),s)-z.begin());
        cout<<(s)<<" "<<ele<<endl;
    }

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    set<int> sett;
    for(int i=0;i<n;i++)
    {
        if(z[i]!=0)
        sett.insert(z[i]);
    }
    z[0]=n;
    sort(z.begin(),z.end());
    int first=lower_bound(z.begin(),z.end(),1)-z.begin();
    cout<<sett.size()<<endl;
    for(auto s:sett)
    {
        int ele = n-(lower_bound(z.begin(),z.end(),s)-z.begin());
        cout<<(s)<<" "<<ele<<endl;
    }
}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    cin>>t;
    // t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    vector<int> zc(n);
    for(int i=0;i<n;i++) zc[i]=z[i];
    sort(zc.begin(),zc.end());

    int ln=0;
    vector<pair<int,int>> ans;
    // for(int i=0;i<n;i++)
    // cout<<z[i]<<" ";
    // cout<<endl;
    // for(int i=0;i<n;i++)
    // cout<<zc[i]<<" ";
    for(int i=1;i<n;i++)
    {
        if(z[n-i]==i)
        {
            // cout<<"FD";
            int cnt=(zc.end()-(lower_bound(zc.begin(),zc.end(),i)));
            ans.push_back({i,cnt});
        }
    }
    cout<<ans.size()+1<<endl;

    for(auto s:ans) cout<<s.first<<" "<<s.second<<endl;
    cout<<n<<" "<<1<<endl;

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    set<int> sett;
    for(int i=0;i<n;i++)
    {
        if(z[i]!=0 && z[i]==n-i)
        sett.insert(z[i]);
    }
    z[0]=n;
    sort(z.begin(),z.end());
    int first=lower_bound(z.begin(),z.end(),1)-z.begin();
    cout<<sett.size()<<endl;
    for(auto s:sett)
    {
        int ele = n-(lower_bound(z.begin(),z.end(),s)-z.begin());
        cout<<(s)<<" "<<ele<<endl;
    }

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
vector<int> zcc(1e5+5);
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;

    // for(int i=0;i<z.size();i++)
    // cout<<z[i]<<" ";
    // cout<<endl;
    for(int i=0;i<n;i++)
    {
        if(z[i]!=0 && z[i]==n-i)
        zcc[z[i]]=1;
    }
    vector<int> zc;
    for(int i=0;i<zcc.size();i++){
        if(zcc[i]==1)
        zc.push_back(i);
    }
    // for(int i=0;i<zc.size();i++)
    // cout<<zc[i]<<" ";
    // cout<<endl;
    sort(z.begin(),z.end());
    int first=lower_bound(z.begin(),z.end(),1)-z.begin();
    cout<<zc.size()<<endl;
    for(auto s:zc)
    {
        int ele = n-(lower_bound(z.begin(),z.end(),s)-z.begin());
        cout<<(s)<<" "<<ele<<endl;
    }

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    vector<int> zc(n);
    for(int i=0;i<n;i++) zc[i]=z[i];
    sort(zc.begin(),zc.end());

    int ln=0;
    vector<pair<int,int>> ans;
    // for(int i=0;i<n;i++)
    // cout<<z[i]<<" ";
    // cout<<endl;
    // for(int i=0;i<n;i++)
    // cout<<zc[i]<<" ";
    for(int i=1;i<n;i++)
    {
        if(z[n-i]==i)
        {
            // cout<<"FD";
            int cnt=(zc.end()-(lower_bound(zc.begin(),zc.end(),i)));
            ans.push_back({i,cnt});
        }
    }
    cout<<ans.size()+1<<endl;
    cout<<n<<" "<<1<<endl;
    for(auto s:ans) cout<<s.first<<" "<<s.second<<endl;

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-i+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) l=i,r=i+z[i]-1;
    }
    z[0]=n;
    vector<int> zc(n);
    for(int i=0;i<n;i++) zc[i]=z[i];
    sort(zc.begin(),zc.end());

    int ln=0;
    vector<pair<int,int>> ans;

    for(int i=1;i<n;i++)
    {
        if(z[n-i]==i)
        {
            // cout<<"FD";
            int cnt=(zc.end()-(lower_bound(zc.begin(),zc.end(),i)));
            ans.push_back({i,cnt});
        }
    }
    cout<<ans.size()+1<<endl;

    for(auto s:ans) cout<<s.first<<" "<<s.second<<endl;
    cout<<n<<" "<<1<<endl;

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-i+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    vector<int> zc(n);
    for(int i=0;i<n;i++) zc[i]=z[i];
    sort(zc.begin(),zc.end());

    int ln=0;
    vector<pair<int,int>> ans;
    // for(int i=0;i<n;i++)
    // cout<<z[i]<<" ";
    // cout<<endl;
    // for(int i=0;i<n;i++)
    // cout<<zc[i]<<" ";
    for(int i=1;i<n;i++)
    {
        if(z[n-i]==i)
        {
            // cout<<"FD";
            int cnt=(zc.end()-(lower_bound(zc.begin(),zc.end(),i)));
            ans.push_back({i,cnt});
        }
    }
    cout<<ans.size()+1<<endl;

    for(auto s:ans) cout<<s.first<<" "<<s.second<<endl;
    cout<<n<<" "<<1<<endl;

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-l+1);
        int j=0,k=i;
        while(k<n && s[k]==s[j]) j++, k++, z[i]++;
        if(i+z[i]-1>r) r=i+z[i]-1;
    }
    z[0]=n;
    set<int> sett;
    for(int i=0;i<n;i++)
    {
        if(z[i]!=0)
        sett.insert(z[i]);
    }
    z[0]=n;
    sort(z.begin(),z.end());
    int first=lower_bound(z.begin(),z.end(),1)-z.begin();
    cout<<sett.size()<<endl;
    for(auto s:sett)
    {
        int ele = n-(lower_bound(z.begin(),z.end(),s)-z.begin());
        cout<<(s)<<" "<<ele<<endl;
    }

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pi 3.14159265358979
using namespace std;
const int N = 3e5 + 5;
void solve()
{
    string s;
    cin>>s;
    int n=s.length();
    // cout<<s<<endl;
    int l=0,r=0;
    vector<int> z(n,0);
    for(int i=1;i<n;i++)
    {
        if(i<=r) z[i]=min(z[i-l],r-i+1);

        while (i + z[i] < n && s[z[i]] == s[i + z[i]])
            ++z[i];

        if(i+z[i]-1>r) l=i,r=i+z[i]-1;
    }
    z[0]=n;
    vector<int> zc(n);
    for(int i=0;i<n;i++) zc[i]=z[i];
    sort(zc.begin(),zc.end());
    // for(int i=0;i<n;i++)
    // cout<<z[i]<<" ";
    // cout<<endl;
    // for(int i=0;i<n;i++)
    // cout<<zc[i]<<" ";
    int ln=0;
    vector<pair<int,int>> ans;

    for(int i=1;i<n;i++)
    {
        if(z[n-i]==i)
        {
            // cout<<"FD";
            int cnt=(zc.end()-(lower_bound(zc.begin(),zc.end(),i)));
            ans.push_back({i,cnt});
        }
    }
    cout<<ans.size()+1<<endl;

    for(auto s:ans) cout<<s.first<<" "<<s.second<<endl;
    cout<<n<<" "<<1<<endl;

}
int main()
{
    ios_base ::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int t;
    // cin>>t;
    t=1;
    while(t--)
    {
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r-i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]+=sumi(n)-sumi(z[i]-1)+1;
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
	int n=s.size();
	vector<int> z(n);
	for(int i=1,l=0,r=0;i<n;i++)
	{
		if(i<=r)
			z[i]=min(r-i+1, z[i-l]);
		while(i+z[i]<n && s[z[i]]==s[i+z[i]])
			z[i]++;
		if(i+z[i]-1>r)
			l=i, r=i+z[i]-1;
	}
	return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]=sumi(n)-sumi(z[i]-1)+1;
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r=i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]+=(sumi(n)-sumi(z[i]-1)+1);
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r=i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]=sumi(n)-sumi(z[i]-1)+1;
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r=i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]+=sumi(n)-sumi(z[i]-1)+1;
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r=i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<=n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]+=(sumi(n)-sumi(z[i]-1)+1);
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iostream>
#define ios   ios_base::sync_with_stdio(false);  cin.tie(0);
typedef  int ll;
using namespace std;
const int M=1e9+7;
const int N=1e5+5;
#define fi first
#define se second
#define pb push_back
ll n;
vector<ll> z_function(string s)
{
    //ll n=s.length();
    vector<ll> z(n,0);
    ll l=0,r=0;
    for(ll i=1;i<n;++i)
    {
        if(i<=r)
        z[i]=min(r-i+1,z[i-l]);
        while(i+z[i]<n && s[z[i]]==s[z[i]+i])
        ++z[i];
        if(i+z[i]-1>r)
        l=i,r-i+z[i]-1;
    }
    return z;
}
ll sum[N];
void add(ll pos,ll val)
{
    while(pos<n)
    {
        sum[pos]+=val;
        pos+=(pos&(-pos));
    }
}
ll sumi(ll pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=sum[pos];
        pos-=(pos&(-pos));
    }
    return res;
}
int main()
{
    ios;
    string s;cin>>s;
     n=s.length();
    vector<ll> z=z_function(s);
    for(ll i=0;i<n;++i)
    {
        if(z[i]!=0)
        add(z[i],1);
    }
    map<ll,ll> ma;
    for(ll i=n-1;i>0;--i)
    {
        if(z[i]!=n-i)
        continue;
        ma[z[i]]=sumi(n)-sumi(z[i]-1)+1;
    }
    ++ma[n];
    cout<<ma.size()<<"\n";
    for(auto x: ma)
    {
        cout<<x.first<<" "<<x.second<<"\n";
    }
}


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 1e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[N], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    fo(i, 1, s.size() - 1, 1) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    fo(i, a.size() + 1, s.size() - 1, 1) {
        ++ct[z[i]];
    }
    foo(i, a.size() - 1, 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("\n%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 2e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[N], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    for (int i = 1; i < s.size(); ++i) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    for (int i = a.size() + 1; i < s.size(); ++i) {
        ++ct[z[i]];
    }
    foo(i, a.size(), 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 1e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[222222], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    for (int i = 1; i < s.size(); ++i) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    for (int i = a.size() + 1; i < s.size(); ++i) {
        ++ct[z[i]];
    }
    foo(i, a.size(), 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 1e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[N], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    fo(i, 1, s.size() - 1, 1) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    fo(i, a.size() + 1, s.size() - 1, 1) {
        ++ct[z[i]];
    }
    foo(i, a.size() - 1, 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 1e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[N], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    fo(i, 1, s.size() - 1, 1) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    fo(i, a.size() + 1, s.size() - 1, 1) {
        ++ct[z[i]];
    }
    foo(i, a.size(), 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


#include <bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define sq(x) (x) * (x)
#define ins insert
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define mp make_pair
#define bit __builtin_popcount
#define all(x) x.begin(),x.end()
#define ll long long
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define er erase

using namespace std;

const int N = 1e5 + 11, mod = 1e9 + 7;
const int INF1 = 2e9;
const ll INF2 = 2e18;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const double EPS = 1e-7;
const double PI = acos(-1.0);

string s;
int ct[N], z[N];
main() {
    file("queue");
    //ios;
    cin >> s;
    int l = 0, r = 0;
    string a = s;
    s = s + '#' + s;
    for (int i = 1; i < s.size(); ++i) {
        if (i <= r) {
            z[i] = min(r - i + 1, z[i - l]);
        }
        while (s[z[i]] == s[i + z[i]] && i + z[i] < s.size()) {
            ++z[i];
        }
        if (i + z[i] - 1 > r) {
            l = i;
            r = i + z[i] - 1;
        }
    }
    for (int i = a.size() + 1; i < s.size(); ++i) {
        ++ct[z[i]];
    }
    foo(i, a.size(), 1, 1) {
        ct[i] += ct[i + 1];
    }
    vector < int > ans;
    fo(i, 1, a.size(), 1) {
        if (z[s.size() - i] == i) {
            ans.eb(i);
        }
    }
    printf("%d\n", ans.size());
    for (const auto & it : ans) {
        printf("%d %d\n", it, ct[it]);
    }
    return 0;
}
/// 243368KZ


//#pragma GCC optimize ("Ofast")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/rope>
#define pb push_back
#define F first
#define S second
#define ins insert
#define mp make_pair
#define fo(i, n1, n, x) for(int i = n1; i <= n; i += x)
#define foo(i, n, n1, x) for(int i = n; i >= n1; i -= x)
#define bit __builtin_popcount
#define md (l + ((r - l) / 2))
#define all(x) x.begin(),x.end()
#define eb emplace_back
#define ub upper_bound
#define lb lower_bound
#define ios ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define file(s) if (fopen(s".in", "r")) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)

using namespace std;
//using namespace __gnu_pbds;
//using namespace __gnu_cxx;

using ll = long long;

//#define int ll

using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<int>;

const int N = 5e3 + 11, mod = 1e9 + 7, mod2 = 998244353;
const int MAX = 1e5 + 11;
const int INF1 = 2e9 + 11;
const ll INF2 = 2e18 + 11;
const double INF3 = 1e8 + 11;
const int base = 500;
const int P = 31;
const int dx[] = {1, -1, 0, 0, 1, 1, -1, -1};
const int dy[] = {0, 0, 1, -1, 1, -1, 1, -1};
const double EPS = 1e-4;
const double PI = acos(-1.0);

//template<typename T> using ordered_set = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename T1, typename T2> inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

string s;
main() {
  file("threesum");
  ios;
  cin >> s;
  string r = s;
  reverse(all(r));
  function<vi(string)> f = [&](string s) {
    vi pi(s.size());
    int n = s.size();
    pi[0] = 0;
    for (int i = 1; i < n; ++i) {
      int j = pi[i - 1];
      while (j > 0 and s[j] != s[i]) j = pi[j - 1];
      if (s[i] == s[j]) ++j;
      pi[i] = j;
    }
    return pi;
  };
  vi pi = f(s);
  vi cnt(s.size() + 1, 0);
  for (int i = 0; i < s.size(); ++i) ++cnt[pi[i]];
  for (int i = s.size() - 1; i; --i) cnt[pi[i - 1]] += cnt[i];
  int cur = pi[s.size() - 1];
  vi ans;
  ans.eb(s.size());
  while (cur > 0) {
    ans.eb(cur);
    cur = pi[cur - 1];
  }
  reverse(all(ans));
  cout << ans.size() << "\n";
  for (int it : ans) cout << it << " " << cnt[it] + 1 << "\n";
  return 0;
}
/**
CCBBDBCC#CCBDBBCC
*/


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    int i, j, n, m, cnt = 0;
    n = sz(s);
    vector<int> pi(n);
    for(i = 1, j = 0; i < n; i++) {
        if (s[i] == s[j])
            pi[i] = pi[i-1] + 1, j++;
        else {
            while(j and s[i] != s[j])
                j = pi[j-1];
            if (s[i] == s[j]) j++;
            pi[i] = j;
        }
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(x > 0) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x]-1;
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    int i, j, n, m, cnt = 0;
    n = sz(s);
    vector<int> pi(n);
    for(i = 1, j = 0; i < n; i++) {
        if (s[i] == s[j])
            pi[i] = pi[i-1] + 1, j++;
        else {
            while(j and s[i] != s[j])
                j = pi[j-1];
            if (s[i] == s[j]) j++;
            pi[i] = j;
        }
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(x) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x]-1;
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    int i, j, n, m, cnt = 0;
    n = sz(s);
    vector<int> pi(n);
    for(i = 1, j = 0; i < n; i++) {
        if (s[i] == s[j])
            pi[i] = pi[i-1] + 1, j++;
        else {
            while(j and s[i] != s[j])
                j = pi[j-1];
            if (s[i] == s[j]) j++;
            pi[i] = j;
        }
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(x > 1) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x]-1;
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    int i, j, n, m, cnt = 0;
    n = sz(s);
    vector<int> pi(n);
    for(i = 1, j = 0; i < n; i++) {
        if (s[i] == s[j])
            pi[i] = pi[i-1] + 1, j++;
        else {
            while(j and s[i] != s[j])
                j = pi[j-1];
            if (s[i] == s[j]) j++;
            pi[i] = j;
        }
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(pi[x]) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x-1];
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    int i, j, n, m, cnt = 0;
    n = sz(s);
    vector<int> pi(n);
    for(i = 1, j = 0; i < n; i++) {
        if (s[i] == s[j])
            pi[i] = pi[i-1] + 1, j++;
        else {
            while(j and s[i] != s[j])
                j = pi[j-1];
            if (s[i] == s[j]) j++;
            pi[i] = j;
        }
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(pi[x]) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x]-1;
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
// #define int long long
using namespace std;
#define e "\n"
#define endl "\n"
#define Tp template<class T>
#define Tp2 template<class T1, class T2>
#define Tps template<class T, class... Ts>
#define Tps2 template<class T1, class T2, class... Ts>
#define ff first
#define ss second
#define rev(Aa) reverse(Aa.begin(),Aa.end())
#define all(Aa) Aa.begin(),Aa.end()
#define lb lower_bound
#define ub upper_bound
#define rsz resize
#define ins insert
#define mp make_pair
#define pb emplace_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(Xx) (int)(Xx).size()
typedef long long ll;
typedef long double ld;
typedef double db;
using pii = pair<int, int>;
const int MOD = 1000000007;  //1e9 + 7
const int INF = 2000000000;  //2e9
const ll DESPACITO = 1000000000000000000;  //1e18
namespace minmax {
    Tp T max(T&& A) { return A; }
    Tp T min(T&& A) { return A; }
    Tp T max(T&& A, T&& B) { return A>B?A:B; }
    Tp T chmin2(T&& A, T&& B) { return A<B?A:B; }
    Tps T max(T&& A, Ts&&... ts) { T B = max(ts...); return A>B?A:B; }
    Tps T min(T&& A, Ts&&... ts) { T B = min(ts...); return A<B?A:B; }
    Tps T chmax(T&& A, Ts&&... ts) { A = max(A, ts...); return A; }
    Tps T chmin(T&& A, Ts&&... ts) { A = min(A, ts...); return A; }
    Tp2 void chmin2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B < A) A = B, Aa = Bb; }
    Tp2 void chmax2(T1&& A, T2&& Aa, T1&& B, T2&& Bb) { if(B > A) A = B, Aa = Bb; }
}
namespace input {
    Tp void re(T&& Xx) { cin >> Xx; }
    Tp2 void re(pair<T1,T2>& Pp) { re(Pp.first); re(Pp.second); }
    Tp void re(vector<T>& Aa) { for(int i = 0; i < sz(Aa); i++) re(Aa[i]); }
    Tp2 void rea(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) re(Aa[i]); }
    Tps2 void rea(T1&& Aa, T2 t, Ts&&... ts) { rea(Aa, t); rea(ts...); }
    Tp2 void rea1(T1&& Aa, T2 t) { for(int i = 1; i <= t; i++) re(Aa[i]); }
    Tps2 void rea1(T1&& Aa, T2 t, Ts&... ts) { rea1(Aa, t); rea1(ts...); }
    Tps void re(T&& t, Ts&... ts) { re(t); re(ts...); }
}
namespace output {
    void pr(int32_t Xx) { cout << Xx; }
    // void pr(num Xx) { cout << Xx; }
    void pr(bool Xx) { cout << Xx; }
    void pr(long long Xx) { cout << Xx; }
    void pr(long long unsigned Xx) { cout << Xx; }
    void pr(double Xx) { cout << Xx; }
    void pr(char Xx) { cout << Xx; }
    void pr(const string& Xx) { cout << Xx; }
    void pr(const char* Xx) { cout << Xx; }
    void pr(const char* Xx, size_t len) { cout << string(Xx, len); }
    void ps() { cout << endl; }
    void pn() { /*do nothing*/ }
    void pw() { pr(" "); }
    void pc() { pr("]"); ps(); }
    Tp2 void pr(const pair<T1,T2>& Xx) { pr(Xx.first); pw(); pr(Xx.second);}
    Tp void pr(const T&);
    bool parse(const char* t) { if(t == e) return true; return false;}
    Tp bool parse(T&& t) { return false;}
    Tp2 bool parsepair(const pair<T1,T2>& Xx) { return true; }
    Tp bool parsepair(T&& t) { return false;}
    Tp2 void psa(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), pw(); ps(); }
    Tp2 void pna(T1&& Aa, T2 t) { for(int i = 0; i < t; i++) pr(Aa[i]), ps(); }
    Tp2 void psa2(T1&& Aa, T2 t1, T2 t2) { for(int i = 0; i < t1; i++) {for(int j = 0; j < t2; j++) pr(Aa[i][j]), pw(); ps();} }
    Tp void pr(const T& Xx) { if(!sz(Xx)) return; bool fst = 1; bool op = 0; if (parsepair(*Xx.begin())) op = 1; for (const auto& Aa: Xx) {if(!fst) pw(); if(op) pr("{"); pr(Aa), fst = 0; if(op) pr("}"); } }
    Tps void pr(const T& t, const Ts&... ts) { pr(t); pr(ts...); }
    Tps void ps(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) {if (!parse(t)) pw(); } ps(ts...); }
    Tp void pn(const T& t) { for (const auto& Aa: t) ps(Aa); }
    Tps void pw(const T& t, const Ts&... ts) { pr(t); if (sizeof...(ts)) pw(); pw(ts...); }
    Tps void pc(const T& t, const Ts&... ts) { bool op = 0; if (parsepair(t)) op = 1; if(op) pr("{"); pr(t); if(op) pr("}"); if (sizeof...(ts)) pr(", "); pc(ts...); }
    namespace trace {
        #define tr(Xx...) pr("[",#Xx,"] = ["), pc(Xx);
        #define tra(Xx, y...) __f0(#Xx, Xx, y)
        #define tran(Xx, n) __fn(n, #Xx, Xx) // TO DO~ variadic multidimensional
        Tp2 void __f(const char* name, const T1& Xx, const T2& y){ pr("[",y,"] = "); ps(Xx); }
        Tps2 void __f(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr("[",y,"]"); __f(open+1, Xx, rest...); }
        Tps2 void __f0(const char* name, const T1& Xx, const T2& y, const Ts&... rest){ const char *open = strchr(name, '['); pr(name, size_t(open-name)); __f(name, Xx, y, rest...); }
        Tp void __fn(int n, const char* name, const T& Xx) { for(int i = 0; i < n; i++) pr(name), __f(name, Xx[i], i); }
    }
}
using namespace minmax;
using namespace input;
using namespace output;
using namespace output::trace;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5 + 5;

vector<int> generate_pi(string s) {
    // pass s as (s + '#' + s)
    int i, n = sz(s);
    vector<int> pi(n);
    for(i = 1; i < n; i++) {
        int p = pi[i-1];
        while(p and s[i] != s[p]) p = pi[p-1];
        pi[i] = p + (s[i] == s[p]);
    }
    return pi;
}

int32_t main() {
    IOS;
    int i, j, n; string s;
    re(s); n = sz(s);
    s = s + '#' + s;
    auto pi = generate_pi(s);
    vector<int> pref(n+1);
    for(i = n; i < sz(s); i++)
        pref[pi[i]]++;
    for(i = sz(pref)-1; i; i--)
        pref[pi[i-1]] += pref[i];
    vector<pii> ans;
    int x = sz(s)-1;
    while(pi[x]) {
        ans.pb(pi[x], pref[pi[x]]);
        x = pi[x]-1;
    }
    rev(ans);
    ps(sz(ans));
    pn(ans);
    return 0;
}


#pragma optimization_level 3
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#include<bits/stdc++.h>

using namespace std;

#define  GODSPEED       ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(15);
#define  f              first
#define  s              second
#define  newl           cout<<"\n";
#define  pb             push_back
#define  mset(a,x)      memset(a,x,sizeof(a))
#define  debv(a)        for(auto it: a)cout<<it<<" ";newl;
#define  deb1(a)        cout<<a<<"\n";
#define  deb2(a,b)      cout<<a<<" "<<b<<"\n";
#define  deb3(a,b,c)    cout<<a<<" "<<b<<" "<<c<<"\n";
#define  deb4(a,b,c,d)  cout<<a<<" "<<b<<" "<<c<<" "<<d<<"\n";
#define  uniq(a)        a.resize(unique(a.begin(), a.end()) - a.begin());
#define  all(a)         a.begin(),a.end()

typedef  long long             ll;
typedef  long double           ld;
typedef  pair<ll,ll>           pll;
typedef  vector<ll>            vll;
typedef  vector<pll>           vpll;

const int  N     =  2e5+5;
const int  mod   =  1e9+7;
const ll   INF   =  0x7f7f7f7f7f7f7f7f;
const int  INFi  =  0x7f7f7f7f;
const int  LEVEL =  log2(N)+1;

ll n, cnt[N];

vector <int> LPS(string s) {
    int n = s.length();
    vector <int> lps(n, 0);
    for (int i = 1; i < n; i++) {
        int j = lps[i-1];
        while(j > 0 && s[i] != s[j]) j = lps[j-1];
        if(s[i] == s[j]) j++;
        lps[i] = j;
        while(j > 0){
        	cnt[j]++;
        	j = lps[j - 1];
        }
    }
    return lps;
}

void solve(){
	string s;
	cin >> s;
	vector <int> lps = LPS(s);
	int j = lps[s.size() - 1];
	vpll ans;
	ans.pb({s.size(), 1});
	while(j){
		ans.pb({j, cnt[j] + 1});
		j = lps[j - 1];
	}
	reverse(all(ans));
	for(auto it : ans) deb2(it.f, it.s)
}

int main(){
	GODSPEED;
	int test = 1;
	//cin >> test;
	for(int i = 1; i <= test; i++){
		solve();
	}
	#ifndef ONLINE_JUDGE
	cout<<"\nTime Elapsed: " << 1.0*clock() / CLOCKS_PER_SEC << " sec\n";
	#endif
}