import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            long a=Long.parseLong(x[0]);
            long b=Long.parseLong(x[1]);
            long c=Long.parseLong(x[2]);
            long d=Long.parseLong(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(b==c && c==d)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }

            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if((a==b && b==c) || (b==c && c==d))
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }
            else if(a==b)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }

            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+(c-1)+" "+(d-1));
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+(a+1));
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+(d-1));
            }
            else
            {
                System.out.print(b+" "+(c-1)+" "+(d-1));
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if((a==b && b==c) || (b==c && c==d))
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }

            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }

            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(b==c && c==d)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }

            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }

            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            long a=Long.parseLong(x[0]);
            long b=Long.parseLong(x[1]);
            long c=Long.parseLong(x[2]);
            long d=Long.parseLong(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(b==c && c==d)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }

            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }

            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            long a=Long.parseLong(x[0]);
            long b=Long.parseLong(x[1]);
            long c=Long.parseLong(x[2]);
            long d=Long.parseLong(x[3]);
            if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            long a=Long.parseLong(x[0]);
            long b=Long.parseLong(x[1]);
            long c=Long.parseLong(x[2]);
            long d=Long.parseLong(x[3]);
            if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else
            {
                System.out.print(a+" "+c+" "+c);
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if(a==b && b==c)
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+(c-1)+" "+(d-1));
            }
            System.out.println();
        }
    }
}


import java.io.*;
import java.util.*;
import java.lang.*;
public class IchihimeAndTriangles
{
    public static void main(String args[])throws IOException
    {
        DataInputStream in=new DataInputStream(System.in);
        int t=Integer.parseInt(in.readLine());
        for(int i=0;i<t;i++)
        {
            String x[]=in.readLine().split(" ");
            int a=Integer.parseInt(x[0]);
            int b=Integer.parseInt(x[1]);
            int c=Integer.parseInt(x[2]);
            int d=Integer.parseInt(x[3]);
            if(a==b && b==c && c==d)
            {
                System.out.print(a+" "+a+" "+a);

            }
            else if((a==b && b==c) || (b==c && c==d))
            {
                System.out.print(a+" "+a+" "+a);
            }
            else if(a==b && c==d)
            {
                System.out.print(a+" "+c+" "+c);
            }
            else if(a==b)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else if(b==c)
            {
                System.out.print(b+" "+b+" "+b);
            }
            else if(c==d)
            {
                System.out.print(b+" "+c+" "+c);
            }

            else if(a+1==b && b+1==c && c+1==d)
            {
                System.out.print(b+" "+c+" "+d);
            }
            else
            {
                System.out.print(b+" "+c+" "+d);
            }
            System.out.println();
        }
    }
}


import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

	public class Main {
	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		while(t--!=0) {
			int a = cin.nextInt();
			int b = cin.nextInt();
			int c = cin.nextInt();
			int d = cin.nextInt();
			System.out.println(b + " " + c + " " + d);
		}
	}
}


import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

	public class Main {
	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		while(t--!=0) {
			int a = cin.nextInt();
			int b = cin.nextInt();
			int c = cin.nextInt();
			int d = cin.nextInt();
			System.out.println(b + " " + c + " " + c);
		}
	}
}


import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import binarySearch.BinarySearch;

public class Main {
	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		while(t--!=0) {
			int a = cin.nextInt();
			int b = cin.nextInt();
			int c = cin.nextInt();
			int d = cin.nextInt();
			System.out.println(b + " " + c + " " + d);
		}
	}
}


import java.util.*;

public class div {
    private static Scanner sc = new Scanner(System.in);
    private static Map<Character, Integer> m = new HashMap<>();
    private static List<Integer> l = new ArrayList<>();
    private static int sum = 0;

    public static void main(String[] args) {
        int t = sc.nextInt();
        // long c = sc.nextLong();
        // boolean f = true;

        for (int i = 0; i < t; i++) {
            long a = sc.nextLong(), b = sc.nextLong(), c = sc.nextLong(), d = sc.nextLong();

            int f1 = 0;
            while ((b + c + d) % 3 != 0) {
                    if (f1 == 0 &&  d - 1 >= c) {
                        d--;
                        f1 = 1;
                    } else {
                        if (f1 == 1 && c - 1 >= b) {
                            c--;
                            f1 = 2;
                        } else {
                            if (f1 == 2 && b - 1 >= a) {
                                b--;
                                f1 = 3;
                            } else {
                                f1 = 0;
                            }
                        }
                    }
            }
            System.out.println(b + " " + c + " " + d);

        }
        // Arrays.sort(a);

    }
}


import java.util.*;

public class div {
    private static Scanner sc = new Scanner(System.in);
    private static Map<Character, Integer> m = new HashMap<>();
    private static List<Integer> l = new ArrayList<>();
    private static int sum = 0;

    public static void main(String[] args) {
        int t = sc.nextInt();
        // long c = sc.nextLong();
        // boolean f = true;

        for (int i = 0; i < t; i++) {
            long a = sc.nextLong(), b = sc.nextLong(), c = sc.nextLong(), d = sc.nextLong();
            System.out.println(b + " " + c + " " + c);

        }
        // Arrays.sort(a);

    }
}


import java.util.*;

public class div {
    private static Scanner sc = new Scanner(System.in);
    private static Map<Character, Integer> m = new HashMap<>();
    private static List<Integer> l = new ArrayList<>();
    private static int sum = 0;

    public static void main(String[] args) {
        int t = sc.nextInt();
        // long c = sc.nextLong();
        // boolean f = true;

        for (int i = 0; i < t; i++) {
            long a = sc.nextLong(), b = sc.nextLong(), c = sc.nextLong(), d = sc.nextLong();
            long mod = (b + c + d) % 3;

            while (mod > 0) {
                if (d - mod >= c) {
                    d -= mod;
                    mod = 0;
                    break;
                } else {
                    mod -= d;
                    d = 0;
                }
                if (c - mod >= b) {
                    c -= mod;
                    mod = 0;
                    break;
                } else {
                    mod -= c;
                    c = 0;
                }
                 if (b - mod >= a) {
                    b -= mod;
                    mod = 0;
                    break;
                } else {
                    mod -= b;
                    b = 0;
                }
            }

            System.out.println(b + " " + c + " " + d);

        }
        // Arrays.sort(a);

    }
}


import java.util.*;

public class div {
    private static Scanner sc = new Scanner(System.in);
    private static Map<Character, Integer> m = new HashMap<>();
    private static List<Integer> l = new ArrayList<>();
    private static int sum = 0;

    public static void main(String[] args) {
        int t = sc.nextInt();
        // long c = sc.nextLong();
        // boolean f = true;

        for (int i = 0; i < t; i++) {
            long a = sc.nextLong(), b = sc.nextLong(), c = sc.nextLong(), d = sc.nextLong();

            int f1 = 0,f2 = 0, f3 = 0;
            while ((b + c + d) % 3 != 0) {
                    if (f1 == 0 && f2 == 0 && f3 ==0) {
                        d--;
                        f1 = 1;
                    } else {
                        if (f1 == 1 && f2 == 0 && f3 == 0) {
                            c--;
                            f2 = 1;
                        } else {
                            if (f1 == 1 && f2 == 1 && f3 == 0) {
                                b--;
                                f3 = 1;
                            } else {
                                f1 = 0; f2 = 0; f3 = 0;
                            }
                        }
                    }
            }
            System.out.println(b + " " + c + " " + d);

        }
        // Arrays.sort(a);

    }
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;

map<int, int> mp;
vector<int> Z_Function(string &text) {
	int n = text.size();
	vector<int> Z(n);
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		if(i <= right)
			Z[i] = min(Z[i - left], right - i + 1);
		while(i + Z[i] < n && text[Z[i]] == text[i + Z[i]])
			++Z[i];
		if(i + Z[i] - 1 > right)
			left = i, right = i + Z[i] - 1;
	}
	return Z;
}

int main() {
	string text;
	cin >> text;
	int n = text.size();
	vector<int> z = Z_Function(text);
	sort(z.begin(), z.end());
	for(int i = 0 ; i < n; ++i) {
		if(z[i] && !mp[z[i]])
			mp[z[i]] = n - i;
	}
	cout << mp.size() << '\n';
	map<int, int> :: iterator it = mp.begin();
	while(it != mp.end()) {
		cout << it-> first << ' ' << it-> second << '\n';
		++it;
	}
}


#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
using namespace std;

const int mxN = 1e5 + 5;
long long cum[mxN], freq[106];
map<int , int> mp, mp2;
string text;

vector< pair<int, int> > Z_Function(string &text1) {
	int n = text.size();
	vector< pair<int, int> > Z(n);
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		++freq[(int)text[i]];
		if(i <= right)
			Z[i].first = min(Z[i - left].first, right - i + 1);
		while(i + Z[i].first < n && text[Z[i].first] == text[i + Z[i].first])
			++Z[i].first;
		if(i + Z[i].first - 1 > right)
			left = i, right = i + Z[i].first - 1;
		Z[i].second = i;
		++mp2[Z[i].first];
	}
	return Z;
}

int get_idx(int x) {
	char c = text[x - 1];
	int low = x - 1, high = text.size() - 1, mid, idx = -1;
	while(low <= high) {
		mid = (low + high) / 2;
		if(text[mid] != c)
			idx = mid, high = mid - 1;
		else
			low = mid + 1;
	}
	return idx;
}

int main() {
	cin >> text;
	int n = text.size();
	vector< pair<int , int> > z = Z_Function(text);
	for(int i = 1; i <= n; ++i)
		cum[i] = cum[i - 1] + mp2[i];
	for(int i = 0 ; i < n; ++i) {
		if(z[i].second + z[i].first == n && !mp[z[i].first]) {
			int idx = get_idx(z[i].first + z[i].second);
			long long tot = 0;
			if(idx == -1)
				tot = cum[(int)text.size()] - cum[z[i].first - 1];
			else
				tot = cum[z[i].first + (idx - z[i].second)] - cum[z[i].first];
			mp[z[i].first] = tot;
		}
	}

	if(text[0] == text[n - 1]) mp[1] = freq[(int)text[0]];
	cout << mp.size() << '\n';
	map<int , int> :: iterator it = mp.begin();
	while(it != mp.end()) {
		cout << it-> first << ' ' << it-> second << '\n';
		++it;
	}
}


#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <cstring>
#include <map>
using namespace std;

const int mxN = 1e5 + 5;
long long cum[mxN], freq[106], ans[mxN], ans2[mxN];
vector< pair<int, int> > Z(mxN);
char text[mxN];

inline void boostIO() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}

void Z_Function() {
	int n = strlen(text);
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		++freq[(int)text[i]];
		if(i <= right)
			Z[i].first = min(Z[i - left].first, right - i + 1);
		while(i + Z[i].first < n && text[Z[i].first] == text[i + Z[i].first])
			++Z[i].first;
		if(i + Z[i].first - 1 > right)
			left = i, right = i + Z[i].first - 1;
		Z[i].second = i;
		++ans2[Z[i].first];
	}
}

int get_idx(int x) {
	char c = text[x - 1];
	int low = x - 1, high = strlen(text) - 1, mid, idx = -1;
	while(low <= high) {
		mid = (low + high) / 2;
		if(text[mid] != c)
			idx = mid, high = mid - 1;
		else
			low = mid + 1;
	}
	return idx;
}

int main() {
//	boostIO();
	scanf("%s", text);
	int n = strlen(text);
	Z_Function();
	for(int i = 1; i <= n; ++i)
		cum[i] = cum[i - 1] + ans2[i];
	int cnt = 0;
	for(int i = 0 ; i < n; ++i) {
		if(Z[i].second + Z[i].first == n && !ans[Z[i].first]) {
			int idx = get_idx(Z[i].first + Z[i].second);
			long long tot = 0;
			if(idx == -1)
				tot = cum[n] - cum[Z[i].first - 1];
			else
				tot = cum[Z[i].first + (idx - Z[i].second)] - cum[Z[i].first];
			ans[Z[i].first] = tot;
			++cnt;
		}
	}
	cout << cnt << '\n';
	for(int i = 1; cnt; ++i) {
		if(ans[i])
			printf("%d %lld\n", i, ans[i]), --cnt;
	}
}


#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
using namespace std;

const int mxN = 1e5 + 5;
long long cum[mxN], freq[106], ans[mxN], ans2[mxN];
vector< pair<int, int> > Z(mxN);

string text;

inline void boostIO() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}

void Z_Function() {
	int n = text.size();
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		++freq[(int)text[i]];
		if(i <= right)
			Z[i].first = min(Z[i - left].first, right - i + 1);
		while(i + Z[i].first < n && text[Z[i].first] == text[i + Z[i].first])
			++Z[i].first;
		if(i + Z[i].first - 1 > right)
			left = i, right = i + Z[i].first - 1;
		Z[i].second = i;
		++ans2[Z[i].first];
	}
}

int get_idx(int x) {
	char c = text[x - 1];
	int low = x - 1, high = text.size() - 1, mid, idx = -1;
	while(low <= high) {
		mid = (low + high) / 2;
		if(text[mid] != c)
			idx = mid, high = mid - 1;
		else
			low = mid + 1;
	}
	return idx;
}

int main() {
	boostIO();
	cin >> text;
	int n = text.size();
	Z_Function();
	for(int i = 1; i <= n; ++i)
		cum[i] = cum[i - 1] + ans2[i];
	int cnt = 0;
	for(int i = 0 ; i < n; ++i) {
		if(Z[i].second + Z[i].first == n && !ans[Z[i].first]) {
			int idx = get_idx(Z[i].first + Z[i].second);
			long long tot = 0;
			if(idx == -1)
				tot = cum[(int)text.size()] - cum[Z[i].first - 1];
			else
				tot = cum[Z[i].first + (idx - Z[i].second)] - cum[Z[i].first];
			ans[Z[i].first] = tot;
			++cnt;
		}
	}
	cout << cnt << '\n';
	for(int i = 1; cnt; ++i) {
		if(ans[i])
			cout << i << ' ' << ans[i] << '\n', --cnt;
	}
}


#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
using namespace std;

map<int , int> mp;
int freq[106];
vector< pair<int, int> > Z_Function(string &text) {
	int n = text.size();
	vector< pair<int, int> > Z(n);
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		++freq[(int)text[i]];
		if(i <= right)
			Z[i].first = min(Z[i - left].first, right - i + 1);
		while(i + Z[i].first < n && text[Z[i].first] == text[i + Z[i].first])
			++Z[i].first;
		if(i + Z[i].first - 1 > right)
			left = i, right = i + Z[i].first - 1;
		Z[i].second = i;
	}
	return Z;
}

int main() {
	string text;
	cin >> text;
	int n = text.size();
	vector< pair<int , int> > z = Z_Function(text);
	sort(z.begin(), z.end());
	for(int i = 0 ; i < n; ++i) {
		if(z[i].second + z[i].first == n && !mp[z[i].first]) {
			mp[z[i].first] = n - i;
		}
	}
	if(text[0] == text[n - 1]) mp[1] = freq[(int)text[0]];
	cout << mp.size() << '\n';
	map<int , int> :: iterator it = mp.begin();
	while(it != mp.end()) {
		cout << it-> first << ' ' << it-> second << '\n';
		++it;
	}
}


#include <iostream>
#include <cstring>
#include <iomanip>
#include <utility>
#include <vector>
using namespace std;

const int mxN = 1e5 + 5;
long long cum[mxN], freq[106], ans[mxN], ans2[mxN];
vector< pair<int, int> > Z(mxN);
vector<pair<int, long long> > last;
char text[mxN];

inline void boostIO() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}

void Z_Function() {
	int n = strlen(text);
	int left, right;
	left = right = 0;
	for(int i = 0; i < n; ++i) {
		++freq[(int)text[i]];
		if(i <= right)
			Z[i].first = min(Z[i - left].first, right - i + 1);
		while(i + Z[i].first < n && text[Z[i].first] == text[i + Z[i].first])
			++Z[i].first;
		if(i + Z[i].first - 1 > right)
			left = i, right = i + Z[i].first - 1;
		Z[i].second = i;
		++ans2[Z[i].first];
	}
}

char c;
int low, high, mid, idx2;
int get_idx(int x) {
	c = text[x - 1];
	low = x - 1, high = strlen(text) - 1, idx2 = -1;
	while(low <= high) {
		mid = (low + high) / 2;
		if(text[mid] != c)
			idx2 = mid, high = mid - 1;
		else
			low = mid + 1;
	}
	return idx2;
}

int main() {
//	boostIO();
//	freopen("t.txt", "r", stdin);
	scanf("%s", text);
	int n = strlen(text);
	Z_Function();
	for(int i = 1; i <= n; ++i)
		cum[i] = cum[i - 1] + ans2[i];
	int idx;
	long long tot;
	for(int i = 0 ; i < n; ++i) {
		if(Z[i].second + Z[i].first == n && !ans[Z[i].first]) {
			 idx = get_idx(Z[i].first + Z[i].second);
			 tot = 0;
			if(idx == -1)
				tot = cum[n] - cum[Z[i].first - 1];
			else
				tot = cum[Z[i].first + (idx - Z[i].second)] - cum[Z[i].first];
			ans[Z[i].first] = tot;
			last.push_back({Z[i].first, tot});
		}
	}
	printf("%d\n", (int)last.size());
	for(pair<int, long long> &x : last)
		printf("%d %lld\n", x.first, x.second);
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define BASE2 (11131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
long long sum[LEN];
bool vi[LEN];
pair<int,long long> ans[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n)
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=0;
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        len=0;
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %lld\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n;
char str[LEN];
int num[LEN];
bool vi[LEN];
int nxt[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
void Get_nxt()
{
    nxt[0]=nxt[1]=0;
    int i=0,j=1;
    while(j<n)
    {
        while(str[i]==str[j]) nxt[++j]=++i,num[i]++;
        while(i&&str[i]!=str[j]) i=nxt[i];
        if(str[i]==str[j]) nxt[++j]=++i,num[i]++;
        else nxt[++j]=i;
    }
}

void Fun()
{
    priority_queue<int> q;
    repe(i,2,n) if(!vi[nxt[i]])
    {
        vi[nxt[i]]=true;
        q.push(vi[nxt[i]]);
    }
    while(!q.empty())
    {
        int tmp=q.top();
        q.pop();
        if(nxt[tmp]) num[nxt[tmp]-1]+=num[tmp];
    }
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        clc(num,0);clc(vi,false);
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        Get_nxt();Fun();
        if(str[0]==str[n-1]) printf("1 %d\n",num[1]+2);
        repe(i,2,n-1) if(a[i]+a[n-i]*b[i]==a[n])
            printf("%d %d\n",i,num[i]+1);
        printf("%d 1\n",n);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
int sum[LEN];
pair<int,int> ans[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}
int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n) if(str[i-1]==str[0])
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=len=0;
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define BASE2 (11131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
int sum[LEN];
bool vi[LEN];
pair<int,int> ans[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};

inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n)
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=num[n];
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        len=0;
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define EPS (1e-6)
#define MAX (1000000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
int sum[LEN];
pair<int,int> ans[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}
int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n)
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=len=0;
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define BASE2 (11131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
int sum[LEN];
bool vi[LEN];
pair<int,int> ans[LEN];
unsigned long long a[LEN];
unsigned long long aa[LEN];
unsigned long long b[LEN]={1};
unsigned long long bb[LEN]={1};
inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1]&&aa[len]+aa[x-1]*bb[len]==aa[x+len-1];
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    repe(i,1,MAX) bb[i]=bb[i-1]*BASE2;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1],aa[i]=aa[i-1]*BASE2+str[i-1];
        clc(num,0);
        repe(i,2,n)
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=num[n];
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        len=0;
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n;
char str[LEN];
int num[LEN];
int sum[LEN];
bool vi[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};

inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n)
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=num[n];
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        repe(i,1,n) if(F(n-i+1,i)) printf("%d %d\n",i,sum[i]+1);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (11131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n,len;
char str[LEN];
int num[LEN];
int sum[LEN];
pair<int,int> ans[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
inline bool F(int x,int len)//以x开头的
{
    return a[len]+a[x-1]*b[len]==a[x+len-1];
}
int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        clc(num,0);
        repe(i,2,n) if(str[i-1]==str[0])
        {
            int l=0,r=n-i+1,mid;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(F(i,mid)) l=mid+1;
                else r=mid-1;
            }
            num[--l]++;
        }
        sum[n]=len=0;
        per(i,n,1) sum[i-1]=sum[i]+num[i-1];
        repe(i,1,n) if(F(n-i+1,i)) ans[len].first=i,ans[len++].second=sum[i]+1;
        printf("%d\n",len);
        rep(i,0,len) printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (11131)
#define EPS (1e-6)
#define MAX (1000000)
#define LEN (MAX+10)

char a[LEN];
int nxt[LEN];
int cnt[LEN];
bool mark[LEN];
int n,c,ans;

void Get_next()
{
    nxt[0]=nxt[1]=0;
    int i=0,j=1;
    while(j<n)
    {
        while(a[i]==a[j]) nxt[++j]=++i;
        while(i&&a[i]!=a[j]) i=nxt[i];
        if(a[i]!=a[j]) nxt[++j]=0;
    }
}

int main()
{
    while(~scanf("%s",a))
    {
        n=(int)strlen(a);
        Get_next();
        repe(i,1,n) cnt[i]=1;
        per(i,n,1) cnt[nxt[i]]+=cnt[i];
        clc(mark,false);ans=1;
        c=nxt[n];
        while(c) mark[c]=true,c=nxt[c],ans++;
        printf("%d\n",ans);
        repe(i,1,n-1) if(mark[i]) printf("%d %d\n",i,cnt[i]);
        printf("%d 1\n",n);
    }
    return 0;
}


|  In English  По-русски
inin864 | Logout

HOMETOPCONTESTSGYMPROBLEMSETGROUPSRATINGAPIHELPVK CUP CALENDAR8 YEARS!

→ Pay attention
Before contest
Codeforces Round #503 (by SIS, Div. 1)
09:44:57
Before contest
Codeforces Round #503 (by SIS, Div. 2)
09:44:57
Register now »
*has extra registration

→ inin864

inin864
User''s contribution into Codeforces community  Contribution: 0
Settings
Blog
Teams
Submissions
Talks
Contests

→ Settings
 Show tags for unsolved problems

→ Last unsolved
#	Name	Last submission
432D	Prefixes and Suffixes	41450796
MAINACMSGURU |
PROBLEMSSUBMITSTATUSSTANDINGSCUSTOM TEST
Submit solution
Codeforces Round #246 (Div. 2)
Problem:	432D - Prefixes and Suffixes

Language:
Source code:

1
Switch off editor Tab size:
Or choose file:

Be careful: there is 50 points penalty for submission which fails the pretests or resubmission (except failure on the first test, denial of judgement or similar verdicts). "Passed pretests" submission verdict doesn't guarantee that the solution is absolutely correct and it will pass system tests.


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repa(i,a,n,b) for(int i = a; i < n; i+=b)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define repea(i,a,n,b) for(int i = a; i <= n; i+=b)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define struct3(A,x,y,z) struct A{int x,y,z;A(){}A(int a,int b,int c):x(a),y(b),z(c){}\
inline bool const operator<(const A &O) const{return z<O.z;}}
#define struct(A,x,y) struct A{int x,y;A(){}A(int a,int b):x(a),y(b){}\
inline bool const operator<(const A &O) const{return x!=O.x?x<O.x:y<O.y;}}
#define check(x,y) (x>=0&&y>=0&&x<n&&y<m)
#define INF (0x3f3f3f3f)
#define MOD (20071027)
#define BASE (131)
#define EPS (1e-6)
#define MAX (100000)
#define LEN (MAX+10)

int n;
char str[LEN];
int num[LEN];
bool vi[LEN];
int nxt[LEN];
unsigned long long a[LEN];
unsigned long long b[LEN]={1};
void Get_nxt()
{
    nxt[0]=nxt[1]=0;
    int i=0,j=1;
    while(j<n)
    {
        while(str[i]==str[j]) nxt[++j]=++i,num[i]++;
        while(i&&str[i]!=str[j]) i=nxt[i];
        if(str[i]==str[j]) nxt[++j]=++i,num[i]++;
        else nxt[++j]=i;
    }
}

void Fun()
{
    priority_queue<int> q;
    repe(i,2,n) if(!vi[nxt[i]])
    {
        vi[nxt[i]]=true;
        q.push(vi[nxt[i]]);
    }
    while(!q.empty())
    {
        int tmp=q.top();
        q.pop();
        if(nxt[tmp]) num[nxt[tmp]]+=num[tmp];
    }
}

int main()
{
    repe(i,1,MAX) b[i]=b[i-1]*BASE;
    while(~scanf("%s",str))
    {
        clc(num,0);clc(vi,false);
        n=(int)strlen(str);
        repe(i,1,n) a[i]=a[i-1]*BASE+str[i-1];
        Get_nxt();Fun();
        if(a[1]+a[n-1]*b[1]==a[n]) printf("1 %d\n",num[1]+2);
        repe(i,2,n-1) if(a[i]+a[n-i]*b[i]==a[n])
            printf("%d %d\n",i,num[i]+1);
        printf("%d 1\n",n);
    }
    return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 100005
int lps[MX];
map<int, int> mp;

void calculate(int j)
{
	while(j>0)mp[j]++, j=lps[j-1];
}

void input_fun()
{
	string str;
	cin>>str;
	int j=0, len=str.length();
	for(int i=1;i<len;i++){
		while(j>0 && str[i]!=str[j])j = lps[j-1];
		if(str[i] == str[j])j++;
		lps[i] = j;
		calculate(j);
	}
	vector<iip> res;
	while(j>0)res.push_back({j, mp[j]}), j=lps[j-1];
	sort(res.begin(), res.end());
	cout<<res.size()+1<<endl;
	for(iip v:res){
		cout<<v.first<<" "<<v.second+1<<endl;
	}
	cout<<len<<" "<<1<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 100005

vector<int> z_function (string s) {
    int n = (int) s.length();
    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;
}

void input_fun()
{
	string str;
	cin>>str;
	int len = str.length();
	vector<int> Z = z_function(str);
	vector<int> cou(len+1, 0);
	for(int i=1;i<len;i++)
		cou[Z[i]]++;
	for(int i=len-1;i>0;i--)cou[i] +=cou[i+1];
	vector<iip> res;
	for(int i=1;i<len;i++){
		if(i+Z[i] == len)res.push_back({Z[i], cou[Z[i]]+1});
	}
	res.push_back({len, 1});
	sort(res.begin(), res.end());
	cout<<res.size()<<endl;
	for(iip v:res)cout<<v.first<<" "<<v.second<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 100005
int lps[MX], cou[MX];

#define MAX_STATE 500
#define MAXC 26
class Aho_Corasick{
    int trie[MAX_STATE][MAXC];  // Make trie in two dimentional array
    int outb[MAX_STATE];        // This is to save pattern that matches in current state using bit
    int fall[MAX_STATE];        // Index of fall
public:
    /*
     * Aho Corasick algorithm. This is bast if there is a number of pattern and we need all the occurance of that patterns.
     * Time complexity O(N + M + K).
     * K is number of pattern.
     * Preprocess Patterns.
     * But preprocessing is a bit complex.
     * Referance : geeksforgeeks.com
	 * Video: Aho Corasick Algo by David Esposito(Super useful, Downloaded).
    */
    void input_fun();
    void preprocessing(vector<string> pats, int k);
    int find_next_state(int state, char ch);
    void searchh(string text, vector<string> pats, int k);

};

void Aho_Corasick::preprocessing(vector<string> pats, int k)
{
    for(int i=0; i<MAX_STATE; i++){     // Initializaton
        outb[i] = 0;
        fall[i] = -1;
        for(int j=0; j<MAXC; j++)
            trie[i][j] = -1;
    }

    int state = 1;

    for(int i=0; i<k; i++){     // In this part make the trie
        string st = pats[i];
        int l = st.length();
        int current_state = 0;

        for(int j=0; j<l; j++){
            int ch = st[j] - 'a';

            if(trie[current_state][ch] == -1)       // Make state for each word
                trie[current_state][ch] = state++;

            current_state = trie[current_state][ch];    // Make chield current
        }
        outb[current_state] |= (1 << i);            // Here a patern ends. So that is output
    }

    queue<int> qu;

    for(int ch=0; ch<MAXC; ch++){
        if(trie[0][ch] != -1){
            fall[trie[0][ch]] = 0;  // All chield of root fall at root
            qu.push(trie[0][ch]);   // Push chields to queue
        }
        else
            trie[0][ch] = 0;     // All non existing root childrens indicates next state 0. This will help
    }

    while(!qu.empty()){
        int cur_state = qu.front();
        qu.pop();

        for(int ch = 0; ch<MAXC; ch++){
            if(trie[cur_state][ch] != -1){          // If the chield exists
                int  fall_state = fall[cur_state];  // Find parents fall

                while(trie[fall_state][ch] == -1)   // If fall state has no children ch then
                    fall_state = fall[fall_state];  // we take fall's fall. This will continue until we reach root.

                fall[trie[cur_state][ch]] = trie[fall_state][ch];   // Fall of current state's ch is fall's matched ch

                outb[trie[cur_state][ch]] |= outb[trie[fall_state][ch]];    // Now output strings of fall's ch will be also
                                                                            // output of this stats ch
                qu.push(trie[cur_state][ch]);
            }
        }
    }
}

int Aho_Corasick::find_next_state(int state, char ch)
{
    int ans = state;
    int chr = ch - 'a';

    while(trie[ans][chr] == -1)     // If not matches then climb up to the root
        ans = fall[ans];

    return trie[ans][chr];
}

vector<iip> res;
void Aho_Corasick::searchh(string text, vector<string> pats, int k)
{
    preprocessing(pats, k);

    int curr_state = 0;
    for(int i=0; i<(int)text.length(); i++){

        curr_state = find_next_state(curr_state, text[i]);  // Find match of text[i] from current state

        if(outb[curr_state] != 0){  // If there is output strings in this state

            for(int j=0; j<MAXC; j++){

                if(outb[curr_state] & (1 << j)){
                   // cout << "String " << pats[j] << " found from " << i-pats[j].length()+1 << " to " << i << endl;
                	cou[pats[j].length()]++;
				}
            }
        }
    }
}
void Aho_Corasick::input_fun()
{
	string str;
	cin>>str;
	int j=0, len=str.length();
	for(char &ch:str)ch += 32;
	for(int i=1;i<len;i++){
		while(j>0 && str[i]!=str[j])j = lps[j-1];
		if(str[i] == str[j])j++;
		lps[i] = j;
	}
	vector<string> all;
	while(j>0)all.push_back(str.substr(0, j)), j=lps[j-1];
	searchh(str, all, all.size());
	for(int i=1;i<MX;i++){
		if(cou[i]>0)res.push_back({i, cou[i]});
	}
	cout<<res.size()+1<<endl;
	for(iip v:res)cout<<v.first<<" "<<v.second<<endl;
	cout<<len<<" "<<1<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);
	Aho_Corasick AHO;

    AHO.input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 100005
int lps[MX], cou[MX];
string str;

#define MAX_STATE 500
#define MAXC 26
class Aho_Corasick{
    int trie[MAX_STATE][MAXC];  // Make trie in two dimentional array
    int outb[MAX_STATE];        // This is to save pattern that matches in current state using bit
    int fall[MAX_STATE];        // Index of fall
public:
    /*
     * Aho Corasick algorithm. This is bast if there is a number of pattern and we need all the occurance of that patterns.
     * Time complexity O(N + M + K).
     * K is number of pattern.
     * Preprocess Patterns.
     * But preprocessing is a bit complex.
     * Referance : geeksforgeeks.com
	 * Video: Aho Corasick Algo by David Esposito(Super useful, Downloaded).
    */
    void input_fun();
    void preprocessing(vector<int> pats, int k);
    int find_next_state(int state, char ch);
    void searchh(string text, vector<int> pats, int k);

};

void Aho_Corasick::preprocessing(vector<int> pats, int k)
{
    for(int i=0; i<MAX_STATE; i++){     // Initializaton
        outb[i] = 0;
        fall[i] = -1;
        for(int j=0; j<MAXC; j++)
            trie[i][j] = -1;
    }

    int state = 1;

    for(int i=0; i<k; i++){     // In this part make the trie
        string st = str.substr(0, pats[i]);
        int l = st.length();
        int current_state = 0;

        for(int j=0; j<l; j++){
            int ch = st[j] - 'a';

            if(trie[current_state][ch] == -1)       // Make state for each word
                trie[current_state][ch] = state++;

            current_state = trie[current_state][ch];    // Make chield current
        }
        outb[current_state] |= (1 << i);            // Here a patern ends. So that is output
    }

    queue<int> qu;

    for(int ch=0; ch<MAXC; ch++){
        if(trie[0][ch] != -1){
            fall[trie[0][ch]] = 0;  // All chield of root fall at root
            qu.push(trie[0][ch]);   // Push chields to queue
        }
        else
            trie[0][ch] = 0;     // All non existing root childrens indicates next state 0. This will help
    }

    while(!qu.empty()){
        int cur_state = qu.front();
        qu.pop();

        for(int ch = 0; ch<MAXC; ch++){
            if(trie[cur_state][ch] != -1){          // If the chield exists
                int  fall_state = fall[cur_state];  // Find parents fall

                while(trie[fall_state][ch] == -1)   // If fall state has no children ch then
                    fall_state = fall[fall_state];  // we take fall's fall. This will continue until we reach root.

                fall[trie[cur_state][ch]] = trie[fall_state][ch];   // Fall of current state's ch is fall's matched ch

                outb[trie[cur_state][ch]] |= outb[trie[fall_state][ch]];    // Now output strings of fall's ch will be also
                                                                            // output of this stats ch
                qu.push(trie[cur_state][ch]);
            }
        }
    }
}

int Aho_Corasick::find_next_state(int state, char ch)
{
    int ans = state;
    int chr = ch - 'a';

    while(trie[ans][chr] == -1)     // If not matches then climb up to the root
        ans = fall[ans];

    return trie[ans][chr];
}

vector<iip> res;
void Aho_Corasick::searchh(string text, vector<int> pats, int k)
{
    preprocessing(pats, k);

    int curr_state = 0;
    for(int i=0; i<(int)text.length(); i++){

        curr_state = find_next_state(curr_state, text[i]);  // Find match of text[i] from current state

        if(outb[curr_state] != 0){  // If there is output strings in this state

            for(int j=0; j<MAXC; j++){

                if(outb[curr_state] & (1 << j)){
                   // cout << "String " << pats[j] << " found from " << i-pats[j].length()+1 << " to " << i << endl;
                	cou[pats[j]]++;
				}
            }
        }
    }
}
void Aho_Corasick::input_fun()
{
	cin>>str;
	int j=0, len=str.length();
	for(char &ch:str)ch += 32;
	for(int i=1;i<len;i++){
		while(j>0 && str[i]!=str[j])j = lps[j-1];
		if(str[i] == str[j])j++;
		lps[i] = j;
	}
	vector<int> all;
	while(j>0)all.push_back(j), j=lps[j-1];
	searchh(str, all, all.size());
	for(int i=1;i<MX;i++){
		if(cou[i]>0)res.push_back({i, cou[i]});
	}
	cout<<res.size()+1<<endl;
	for(iip v:res)cout<<v.first<<" "<<v.second<<endl;
	cout<<len<<" "<<1<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);
	Aho_Corasick AHO;

    AHO.input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 100005
int lps[MX], cou[MX];
string str;

#define MAX_STATE 100005
#define MAXC 27
class Aho_Corasick{
    int trie[MAX_STATE][MAXC];  // Make trie in two dimentional array
    int outb[MAX_STATE];        // This is to save pattern that matches in current state using bit
    int fall[MAX_STATE];        // Index of fall
public:
    /*
     * Aho Corasick algorithm. This is bast if there is a number of pattern and we need all the occurance of that patterns.
     * Time complexity O(N + M + K).
     * K is number of pattern.
     * Preprocess Patterns.
     * But preprocessing is a bit complex.
     * Referance : geeksforgeeks.com
	 * Video: Aho Corasick Algo by David Esposito(Super useful, Downloaded).
    */
    void input_fun();
    void preprocessing(vector<int> pats, int k);
    int find_next_state(int state, char ch);
    void searchh(string text, vector<int> pats, int k);

};

void Aho_Corasick::preprocessing(vector<int> pats, int k)
{
    for(int i=0; i<MAX_STATE; i++){     // Initializaton
        outb[i] = 0;
        fall[i] = -1;
        for(int j=0; j<MAXC; j++)
            trie[i][j] = -1;
    }

    int state = 1;

    for(int i=0; i<k; i++){     // In this part make the trie
        string st = str.substr(0, pats[i]);
        int l = st.length();
        int current_state = 0;

        for(int j=0; j<l; j++){
            int ch = st[j] - 'a';

            if(trie[current_state][ch] == -1)       // Make state for each word
                trie[current_state][ch] = state++;

            current_state = trie[current_state][ch];    // Make chield current
        }
        outb[current_state] |= (1 << i);            // Here a patern ends. So that is output
    }

    queue<int> qu;

    for(int ch=0; ch<MAXC; ch++){
        if(trie[0][ch] != -1){
            fall[trie[0][ch]] = 0;  // All chield of root fall at root
            qu.push(trie[0][ch]);   // Push chields to queue
        }
        else
            trie[0][ch] = 0;     // All non existing root childrens indicates next state 0. This will help
    }

    while(!qu.empty()){
        int cur_state = qu.front();
        qu.pop();

        for(int ch = 0; ch<MAXC; ch++){
            if(trie[cur_state][ch] != -1){          // If the chield exists
                int  fall_state = fall[cur_state];  // Find parents fall

                while(trie[fall_state][ch] == -1)   // If fall state has no children ch then
                    fall_state = fall[fall_state];  // we take fall's fall. This will continue until we reach root.

                fall[trie[cur_state][ch]] = trie[fall_state][ch];   // Fall of current state's ch is fall's matched ch

                outb[trie[cur_state][ch]] |= outb[trie[fall_state][ch]];    // Now output strings of fall's ch will be also
                                                                            // output of this stats ch
                qu.push(trie[cur_state][ch]);
            }
        }
    }
}

int Aho_Corasick::find_next_state(int state, char ch)
{
    int ans = state;
    int chr = ch - 'a';

    while(trie[ans][chr] == -1)     // If not matches then climb up to the root
        ans = fall[ans];

    return trie[ans][chr];
}

vector<iip> res;
void Aho_Corasick::searchh(string text, vector<int> pats, int k)
{
    preprocessing(pats, k);

    int curr_state = 0;
    for(int i=0; i<(int)text.length(); i++){

        curr_state = find_next_state(curr_state, text[i]);  // Find match of text[i] from current state

        if(outb[curr_state] != 0){  // If there is output strings in this state

            for(int j=0; j<MAXC; j++){

                if(outb[curr_state] & (1 << j)){
                   // cout << "String " << pats[j] << " found from " << i-pats[j].length()+1 << " to " << i << endl;
                	cou[pats[j]]++;
				}
            }
        }
    }
}
void Aho_Corasick::input_fun()
{
	cin>>str;
	int j=0, len=str.length();
	for(char &ch:str)ch += 32;
	for(int i=1;i<len;i++){
		while(j>0 && str[i]!=str[j])j = lps[j-1];
		if(str[i] == str[j])j++;
		lps[i] = j;
	}
	vector<int> all;
	while(j>0)all.push_back(j), j=lps[j-1];
	searchh(str, all, all.size());
	for(int i=1;i<MX;i++){
		if(cou[i]>0)res.push_back({i, cou[i]});
	}
	cout<<res.size()+1<<endl;
	for(iip v:res)cout<<v.first<<" "<<v.second<<endl;
	cout<<len<<" "<<1<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);
	Aho_Corasick AHO;

    AHO.input_fun();
return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define VV vector
#define pb push_back
#define bitc  __builtin_popcountl
#define m_p make_pair
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);

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

int ans[n+1]={0};
for(int i=0;i<n;++i)
{
    ans[lps[i]]++;
}
for(int i=n-1;i>=0;--i)
{
    //cout<<i<<" "<<ans[i]<<" "<<lps[i-1]<<"\n";
    ans[lps[i-1]]+=ans[i];
}
ans[n]=1;
int x=lps[n-1];
vector<pair<int,int> > v;
while(x!=0)
{
    v.push_back(make_pair(x,ans[x]));
    x=lps[x-1];
}
cout<<v.size()+1<<"\n";
for(int i=(int)v.size()-1;i>=0;--i)
{
    cout<<v[i].first<<" "<<v[i].second+1<<"\n";
}
cout<<n<<" 1";
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define VV vector
#define pb push_back
#define bitc  __builtin_popcountl
#define m_p make_pair
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s;
cin>>s;
int n=s.length();
int lps[n]={0};
lps[0]=0;
for(int i=1;i<s.length();++i)
{
    int j=i-1;
    while(lps[j]!=0&&s[lps[j]]!=s[i])
        j=lps[j]-1;
    if(s[lps[j]]==s[i])
    {
        lps[i]=lps[j]+1;
    }
    else
    {
        lps[i]=0;
    }
}
int ans[n+1]={0};
for(int i=0;i<n;++i)
{
    int j=i;
    while(lps[j]!=0)
    {
        ans[lps[j]]++;
        j=lps[j]-1;
    }
}
ans[n]=1;
int x=lps[n-1];
vector<pair<int,int> > v;
while(x!=0)
{
    v.push_back(make_pair(x,ans[x]));
    x=lps[x-1];
}
cout<<v.size()+1<<"\n";
for(int i=(int)v.size()-1;i>=0;--i)
{
    cout<<v[i].first<<" "<<v[i].second+1<<"\n";
}
cout<<n<<" 1";
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define VV vector
#define pb push_back
#define bitc  __builtin_popcountl
#define m_p make_pair
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s;
cin>>s;
int n=s.length();
int lps[n]={0};
lps[0]=0;
for(int i=1;i<s.length();++i)
{
    int j=i-1;
    while(lps[j]!=0&&s[lps[j]]!=s[i])
        j=lps[j]-1;
    if(s[lps[j]]==s[i])
    {
        lps[i]=lps[j]+1;
    }
    else
    {
        lps[i]=0;
    }
}

int ans[n+1]={0};
for(int i=0;i<n;++i)
{
    ans[lps[i]]++;
}
for(int i=n-1;i>=0;--i)
{
    //cout<<i<<" "<<ans[i]<<" "<<lps[i-1]<<"\n";
    ans[lps[i-1]]+=ans[i];
}
ans[n]=1;
int x=lps[n-1];
vector<pair<int,int> > v;
while(x!=0)
{
    v.push_back(make_pair(x,ans[x]));
    x=lps[x-1];
}
cout<<v.size()+1<<"\n";
for(int i=(int)v.size()-1;i>=0;--i)
{
    cout<<v[i].first<<" "<<v[i].second+1<<"\n";
}
cout<<n<<" 1";
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define VV vector
#define pb push_back
#define bitc  __builtin_popcountl
#define m_p make_pair
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s;
cin>>s;
int n=s.length();
int lps[1000000]={0};
lps[0]=0;
for(int i=1;i<s.length();++i)
{
    int j=i-1;
    while(lps[j]!=0&&s[lps[j]]!=s[i])
        j=lps[j]-1;
    if(s[lps[j]]==s[i])
    {
        lps[i]=lps[j]+1;
    }
    else
    {
        lps[i]=0;
    }
}

int ans[1000001]={0};
for(int i=0;i<n;++i)
{
    ans[lps[i]]++;
}
for(int i=n-1;i>=0;--i)
{
    //cout<<i<<" "<<ans[i]<<" "<<lps[i-1]<<"\n";
    ans[lps[i-1]]+=ans[i];
}
ans[n]=1;
int x=lps[n-1];
vector<pair<int,int> > v;
while(x!=0)
{
    v.push_back(make_pair(x,ans[x]));
    x=lps[x-1];
}
cout<<v.size()+1<<"\n";
for(int i=(int)v.size()-1;i>=0;--i)
{
    cout<<v[i].first<<" "<<v[i].second+1<<"\n";
}
cout<<n<<" 1";
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define VV vector
#define pb push_back
#define bitc  __builtin_popcountl
#define m_p make_pair
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s;
cin>>s;
int n=s.length();
int lps[n]={0};
lps[0]=0;
for(int i=1;i<s.length();++i)
{
    int j=i-1;
    while(lps[j]!=0&&s[lps[j]]!=s[i])
        j=lps[j];
    if(s[lps[j]]==s[i])
    {
        lps[i]=lps[j]+1;
    }
    else
    {
        lps[i]=0;
    }
}
int ans[n+1]={0};
for(int i=0;i<n;++i)
{
    int j=i;
    while(lps[j]!=0)
    {
        ans[lps[j]]++;
        j=lps[j]-1;
    }
}
ans[n]=1;
int x=lps[n-1];
vector<pair<int,int> > v;
while(x!=0)
{
    v.push_back(make_pair(x,ans[x]));
    x=lps[x-1];
}
cout<<v.size()+1<<"\n";
for(int i=(int)v.size()-1;i>=0;--i)
{
    cout<<v[i].first<<" "<<v[i].second+1<<"\n";
}
cout<<n<<" 1";
}


/***************************************** START OF TEMPLATE *********************************************/
#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>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define  SPEED           ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(10);
#define  randomINIT      mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define  foo(i,a,n)      for(ll i = (a); i <= n; i++)
#define  frr(i,a,n)      for(ll i = (a); i >= n; i--)
#define  fo(i,n)         for(ll i = 0; i < n; i++)
#define  newl            cout<<"\n";
#define  f               first
#define  s               second
#define  pb              push_back
#define  mp              make_pair
#define  sym(s)          s="#"+s+"#";
#define  sqr(v)          v*v;
#define  all(x)          (x).begin(),(x).end()
#define  alll(x,n)       x+1, x+n+1
#define  uniq(a)         a.resize(unique(a.begin(), a.end()) - a.begin());
#define  mset(x,val)     memset(x,val,sizeof(x))
#define  mset1d(a,n,v)   foo(i,0,n+5)a[i]=v;
#define  mset2d(a,n,m,v) foo(i,0,n+5)foo(j,0,m+5)a[i][j]=v;
#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  debp(a)         cout<<a.f<<" "<<a.s<<"\n";
#define  debv(a)         for(auto it: a)cout<<it<<" ";newl;
#define  debm(a)         for(auto it: a)cout<<"{"<<it.f<<","<<it.s<<"}, ";newl;
#define  deb1d(a,n)      foo(i,1,n)cout<<a[i]<<" ";newl;
#define  deb2d(a,n,m)    foo(i,1,n){foo(j,1,m){cout<<a[i][j]<<" ";}newl;}

template <typename T>
using  ordered_set =  tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;
using  ll          =  long long;
using  ull         =  unsigned long long;
using  ld          =  long double;
using  pll         =  pair<ll,ll>;
using  vll         =  vector<ll>;
using  vpll        =  vector<pll>;

const ld   PI    =  3.14159265358979323846;
const ll   MOD   =  1e+9+7;
const ll   INF   =  LLONG_MAX;
const int  INFi  =  INT_MAX;
const ll   N     =  2e+5+8;

vll adj[N]; ll vis[N];
ll dx4[]={0,1,0,-1}, dy4[]={1,0,-1,0};

ll test_cases = 1; randomINIT;

/*********************************************************************************************************/
ll n;
string s;
ll cnt[N], pf[N];
vpll res;

/***************************************** VARIABLE DECLARATIONS *****************************************/
void compute_prefix_function(string s){
    pf[0] = pf[1] = 0;
    int n = s.size();
    for(int i = 2; i <= n; i++){
        int j = pf[i-1] + 1;
        while(j > 1 && s[j] != s[i]){
            j = pf[j-1] + 1;
        }
        pf[i] = j == 1 ? (s[1] == s[i]): j;
    }

    for (int i = 1; i <= n; i++)
        cnt[pf[i]]++;
    for (int i = n; i >= 1; i--)
        cnt[pf[i]] += cnt[i];
    for (int i = 1; i <= n; i++)
        cnt[i]++;
}
string rev(string s){
    reverse(all(s));
    return s;
}
void solve(string s){
    compute_prefix_function(s);
    int i = n;
    int j = pf[i-1] + 1;
    vll good_lengths;
    good_lengths.pb(n);
    while(j > 1){
        if(s[j] == s[i]){
            good_lengths.pb(j);
        }
        j = pf[j-1] + 1;
    }
    if(s[1] == s[n]) good_lengths.pb(1);
    reverse(all(good_lengths));
    deb1(good_lengths.size());
    for(auto it: good_lengths){
        deb2(it,cnt[it]);
    }

}
/***************************************** FUNCTION IMPLEMENTATIONS **************************************/

/***************************************** START OF MAIN FUNCTION ****************************************/
void MAIN(ll tc){
    cin>>s;
    n = s.size();
    sym(s);
    solve(s);
}

int main(){
    SPEED;

    //cin>>test_cases;
    foo(i,1,test_cases){
        MAIN(i);
    }
}


/***************************************** START OF TEMPLATE *********************************************/
#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>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define  SPEED           ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(10);
#define  randomINIT      mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define  foo(i,a,n)      for(ll i = (a); i <= n; i++)
#define  frr(i,a,n)      for(ll i = (a); i >= n; i--)
#define  fo(i,n)         for(ll i = 0; i < n; i++)
#define  newl            cout<<"\n";
#define  f               first
#define  s               second
#define  pb              push_back
#define  mp              make_pair
#define  sym(s)          s="#"+s+"#";
#define  sqr(v)          v*v;
#define  all(x)          (x).begin(),(x).end()
#define  alll(x,n)       x+1, x+n+1
#define  uniq(a)         a.resize(unique(a.begin(), a.end()) - a.begin());
#define  mset(x,val)     memset(x,val,sizeof(x))
#define  mset1d(a,n,v)   foo(i,0,n+5)a[i]=v;
#define  mset2d(a,n,m,v) foo(i,0,n+5)foo(j,0,m+5)a[i][j]=v;
#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  debp(a)         cout<<a.f<<" "<<a.s<<"\n";
#define  debv(a)         for(auto it: a)cout<<it<<" ";newl;
#define  debm(a)         for(auto it: a)cout<<"{"<<it.f<<","<<it.s<<"}, ";newl;
#define  deb1d(a,n)      foo(i,1,n)cout<<a[i]<<" ";newl;
#define  deb2d(a,n,m)    foo(i,1,n){foo(j,1,m){cout<<a[i][j]<<" ";}newl;}

template <typename T>
using  ordered_set =  tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;
using  ll          =  long long;
using  ull         =  unsigned long long;
using  ld          =  long double;
using  pll         =  pair<ll,ll>;
using  vll         =  vector<ll>;
using  vpll        =  vector<pll>;

const ld   PI    =  3.14159265358979323846;
const ll   MOD   =  1e+9+7;
const ll   INF   =  LLONG_MAX;
const int  INFi  =  INT_MAX;
const ll   N     =  2e+5+8;

vll adj[N]; ll vis[N];
ll dx4[]={0,1,0,-1}, dy4[]={1,0,-1,0};

ll test_cases = 1; randomINIT;

/*********************************************************************************************************/
ll n;
string s;
ll cnt[N], pf[N];
vpll res;

/***************************************** VARIABLE DECLARATIONS *****************************************/
void compute_prefix_function(string s){
    pf[0] = pf[1] = 0;
    int n = s.size();
    for(int i = 2; i <= n; i++){
        int j = pf[i-1] + 1;
        while(j > 1 && s[j] != s[i]){
            j = pf[j-1] + 1;
        }
        pf[i] = j == 1 ? (s[1] == s[i]): j;
    }

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

    /*deb1d(cnt,n);
    deb1d(pf,n);
    deb1d(s,n);*/
}
string rev(string s){
    reverse(all(s));
    return s;
}
void solve(string s){
    compute_prefix_function(s);
    int i = n;
    int j = pf[i-1] + 1;
    vll good_lengths;
    if(rev(s) == s) good_lengths.pb(n);
    if(pf[n]) good_lengths.pb(pf[n]);
    while(j > 1){
        j = pf[j-1] + 1;
        if(s[j] == s[i]){
            good_lengths.pb(j);
        }
    }
    reverse(all(good_lengths));
    deb1(good_lengths.size());
    for(auto it: good_lengths){
        deb2(it,cnt[it]);
    }

}
/***************************************** FUNCTION IMPLEMENTATIONS **************************************/

/***************************************** START OF MAIN FUNCTION ****************************************/
void MAIN(ll tc){
    cin>>s;
    n = s.size();
    sym(s);
    solve(s);
}

int main(){
    SPEED;

    //cin>>test_cases;
    foo(i,1,test_cases){
        MAIN(i);
    }
}


/***************************************** START OF TEMPLATE *********************************************/
#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>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define  SPEED           ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(10);
#define  randomINIT      mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define  foo(i,a,n)      for(ll i = (a); i <= n; i++)
#define  frr(i,a,n)      for(ll i = (a); i >= n; i--)
#define  fo(i,n)         for(ll i = 0; i < n; i++)
#define  newl            cout<<"\n";
#define  f               first
#define  s               second
#define  pb              push_back
#define  mp              make_pair
#define  sym(s)          s="#"+s+"#";
#define  sqr(v)          v*v;
#define  all(x)          (x).begin(),(x).end()
#define  alll(x,n)       x+1, x+n+1
#define  uniq(a)         a.resize(unique(a.begin(), a.end()) - a.begin());
#define  mset(x,val)     memset(x,val,sizeof(x))
#define  mset1d(a,n,v)   foo(i,0,n+5)a[i]=v;
#define  mset2d(a,n,m,v) foo(i,0,n+5)foo(j,0,m+5)a[i][j]=v;
#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  debp(a)         cout<<a.f<<" "<<a.s<<"\n";
#define  debv(a)         for(auto it: a)cout<<it<<" ";newl;
#define  debm(a)         for(auto it: a)cout<<"{"<<it.f<<","<<it.s<<"}, ";newl;
#define  deb1d(a,n)      foo(i,1,n)cout<<a[i]<<" ";newl;
#define  deb2d(a,n,m)    foo(i,1,n){foo(j,1,m){cout<<a[i][j]<<" ";}newl;}

template <typename T>
using  ordered_set =  tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;
using  ll          =  long long;
using  ull         =  unsigned long long;
using  ld          =  long double;
using  pll         =  pair<ll,ll>;
using  vll         =  vector<ll>;
using  vpll        =  vector<pll>;

const ld   PI    =  3.14159265358979323846;
const ll   MOD   =  1e+9+7;
const ll   INF   =  LLONG_MAX;
const int  INFi  =  INT_MAX;
const ll   N     =  2e+5+8;

vll adj[N]; ll vis[N];
ll dx4[]={0,1,0,-1}, dy4[]={1,0,-1,0};

ll test_cases = 1; randomINIT;

/*********************************************************************************************************/
ll n;
string s;
ll cnt[N], pf[N];
vpll res;

/***************************************** VARIABLE DECLARATIONS *****************************************/
void compute_prefix_function(string s){
    pf[0] = pf[1] = 0;
    int n = s.size();
    for(int i = 2; i <= n; i++){
        int j = pf[i-1] + 1;
        while(j > 1 && s[j] != s[i]){
            j = pf[j-1] + 1;
        }
        pf[i] = j == 1 ? (s[1] == s[i]): j;
    }

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

    /*deb1d(cnt,n);
    deb1d(pf,n);
    deb1d(s,n);*/
}
string rev(string s){
    reverse(all(s));
    return s;
}
void solve(string s){
    compute_prefix_function(s);
    int i = n;
    int j = pf[i-1] + 1;
    vll good_lengths;
    if(rev(s) == s) good_lengths.pb(n);
    good_lengths.pb(pf[n]);
    while(j > 1){
        j = pf[j-1] + 1;
        if(s[j] == s[i]){
            good_lengths.pb(j);
        }
    }
    reverse(all(good_lengths));
    for(auto it: good_lengths){
        deb2(it,cnt[it]);
    }

}
/***************************************** FUNCTION IMPLEMENTATIONS **************************************/

/***************************************** START OF MAIN FUNCTION ****************************************/
void MAIN(ll tc){
    cin>>s;
    n = s.size();
    sym(s);
    solve(s);
}

int main(){
    SPEED;

    //cin>>test_cases;
    foo(i,1,test_cases){
        MAIN(i);
    }
}


/***************************************** START OF TEMPLATE *********************************************/
#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>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define  SPEED           ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(10);
#define  randomINIT      mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define  foo(i,a,n)      for(ll i = (a); i <= n; i++)
#define  frr(i,a,n)      for(ll i = (a); i >= n; i--)
#define  fo(i,n)         for(ll i = 0; i < n; i++)
#define  newl            cout<<"\n";
#define  f               first
#define  s               second
#define  pb              push_back
#define  mp              make_pair
#define  sym(s)          s="#"+s+"#";
#define  sqr(v)          v*v;
#define  all(x)          (x).begin(),(x).end()
#define  alll(x,n)       x+1, x+n+1
#define  uniq(a)         a.resize(unique(a.begin(), a.end()) - a.begin());
#define  mset(x,val)     memset(x,val,sizeof(x))
#define  mset1d(a,n,v)   foo(i,0,n+5)a[i]=v;
#define  mset2d(a,n,m,v) foo(i,0,n+5)foo(j,0,m+5)a[i][j]=v;
#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  debp(a)         cout<<a.f<<" "<<a.s<<"\n";
#define  debv(a)         for(auto it: a)cout<<it<<" ";newl;
#define  debm(a)         for(auto it: a)cout<<"{"<<it.f<<","<<it.s<<"}, ";newl;
#define  deb1d(a,n)      foo(i,1,n)cout<<a[i]<<" ";newl;
#define  deb2d(a,n,m)    foo(i,1,n){foo(j,1,m){cout<<a[i][j]<<" ";}newl;}

template <typename T>
using  ordered_set =  tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;
using  ll          =  long long;
using  ull         =  unsigned long long;
using  ld          =  long double;
using  pll         =  pair<ll,ll>;
using  vll         =  vector<ll>;
using  vpll        =  vector<pll>;

const ld   PI    =  3.14159265358979323846;
const ll   MOD   =  1e+9+7;
const ll   INF   =  LLONG_MAX;
const int  INFi  =  INT_MAX;
const ll   N     =  2e+5+8;

vll adj[N]; ll vis[N];
ll dx4[]={0,1,0,-1}, dy4[]={1,0,-1,0};

ll test_cases = 1; randomINIT;

/*********************************************************************************************************/
ll n;
string s;
ll cnt[N], pf[N];
vpll res;

/***************************************** VARIABLE DECLARATIONS *****************************************/
void compute_prefix_function(string s){
    pf[0] = pf[1] = 0;
    int n = s.size();
    for(int i = 2; i <= n; i++){
        int j = pf[i-1] + 1;
        while(j > 1 && s[j] != s[i]){
            j = pf[j-1] + 1;
        }
        pf[i] = j == 1 ? (s[1] == s[i]): j;
    }

    for (int i = 1; i <= n; i++)
        cnt[pf[i]]++;
    for (int i = n; i >= 1; i--)
        cnt[pf[i]] += cnt[i];
    for (int i = 1; i <= n; i++)
        cnt[i]++;
}
string rev(string s){
    reverse(all(s));
    return s;
}
void solve(string s){
    compute_prefix_function(s);
    int i = n;
    int j = pf[i-1] + 1;
    vll good_lengths;
    good_lengths.pb(n);
    while(j > 1){
        if(s[j] == s[i]){
            good_lengths.pb(j);
        }
        j = pf[j-1] + 1;
    }
    if(s[1] == s[n] && n != 1) good_lengths.pb(1);
    reverse(all(good_lengths));
    deb1(good_lengths.size());
    for(auto it: good_lengths){
        deb2(it,cnt[it]);
    }

}
/***************************************** FUNCTION IMPLEMENTATIONS **************************************/

/***************************************** START OF MAIN FUNCTION ****************************************/
void MAIN(ll tc){
    cin>>s;
    n = s.size();
    sym(s);
    solve(s);
}

int main(){
    SPEED;

    //cin>>test_cases;
    foo(i,1,test_cases){
        MAIN(i);
    }
}


/***************************************** START OF TEMPLATE *********************************************/
#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>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;

#define  SPEED           ios:: sync_with_stdio(0);cin.tie(0);cout.tie(0);cout<<fixed;cout<<setprecision(10);
#define  randomINIT      mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define  foo(i,a,n)      for(ll i = (a); i <= n; i++)
#define  frr(i,a,n)      for(ll i = (a); i >= n; i--)
#define  fo(i,n)         for(ll i = 0; i < n; i++)
#define  newl            cout<<"\n";
#define  f               first
#define  s               second
#define  pb              push_back
#define  mp              make_pair
#define  sym(s)          s="#"+s+"#";
#define  sqr(v)          v*v;
#define  all(x)          (x).begin(),(x).end()
#define  alll(x,n)       x+1, x+n+1
#define  uniq(a)         a.resize(unique(a.begin(), a.end()) - a.begin());
#define  mset(x,val)     memset(x,val,sizeof(x))
#define  mset1d(a,n,v)   foo(i,0,n+5)a[i]=v;
#define  mset2d(a,n,m,v) foo(i,0,n+5)foo(j,0,m+5)a[i][j]=v;
#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  debp(a)         cout<<a.f<<" "<<a.s<<"\n";
#define  debv(a)         for(auto it: a)cout<<it<<" ";newl;
#define  debm(a)         for(auto it: a)cout<<"{"<<it.f<<","<<it.s<<"}, ";newl;
#define  deb1d(a,n)      foo(i,1,n)cout<<a[i]<<" ";newl;
#define  deb2d(a,n,m)    foo(i,1,n){foo(j,1,m){cout<<a[i][j]<<" ";}newl;}

template <typename T>
using  ordered_set =  tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;
using  ll          =  long long;
using  ull         =  unsigned long long;
using  ld          =  long double;
using  pll         =  pair<ll,ll>;
using  vll         =  vector<ll>;
using  vpll        =  vector<pll>;

const ld   PI    =  3.14159265358979323846;
const ll   MOD   =  1e+9+7;
const ll   INF   =  LLONG_MAX;
const int  INFi  =  INT_MAX;
const ll   N     =  2e+5+8;

vll adj[N]; ll vis[N];
ll dx4[]={0,1,0,-1}, dy4[]={1,0,-1,0};

ll test_cases = 1; randomINIT;

/*********************************************************************************************************/
ll n;
string s;
ll cnt[N], pf[N];
vpll res;

/***************************************** VARIABLE DECLARATIONS *****************************************/
void compute_prefix_function(string s){
    pf[0] = pf[1] = 0;
    int n = s.size();
    for(int i = 2; i <= n; i++){
        int j = pf[i-1] + 1;
        while(j > 1 && s[j] != s[i]){
            j = pf[j-1] + 1;
        }
        pf[i] = j == 1 ? (s[1] == s[i]): j;
    }

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

    /*deb1d(cnt,n);
    deb1d(pf,n);
    deb1d(s,n);*/
}
string rev(string s){
    reverse(all(s));
    return s;
}
void solve(string s){
    compute_prefix_function(s);
    int i = n;
    int j = pf[i-1] + 1;
    vll good_lengths;
    if(rev(s) == s) good_lengths.pb(n);
    good_lengths.pb(pf[n]);
    while(j > 1){
        j = pf[j-1] + 1;
        if(s[j] == s[i]){
            good_lengths.pb(j);
        }
    }
    reverse(all(good_lengths));
    deb1(good_lengths.size());
    for(auto it: good_lengths){
        deb2(it,cnt[it]);
    }

}
/***************************************** FUNCTION IMPLEMENTATIONS **************************************/

/***************************************** START OF MAIN FUNCTION ****************************************/
void MAIN(ll tc){
    cin>>s;
    n = s.size();
    sym(s);
    solve(s);
}

int main(){
    SPEED;

    //cin>>test_cases;
    foo(i,1,test_cases){
        MAIN(i);
    }
}