Problem:
Score : 900 points

Problem Statement

Let x be a string of length at least 1.
We will call x a good string, if for any string y and any integer k (k \geq 2), the string obtained by concatenating k copies of y is different from x.
For example, a, bbc and cdcdc are good strings, while aa, bbbb and cdcdcd are not.

Let w be a string of length at least 1.
For a sequence F=(\,f_1,\,f_2,\,...,\,f_m) consisting of m elements,
we will call F a good representation of w, if the following conditions are both satisfied:

For any i \, (1 \leq i \leq m), f_i is a good string.

The string obtained by concatenating f_1,\,f_2,\,...,\,f_m in this order, is w.

For example, when w=aabb, there are five good representations of w:

(aabb)

(a,abb)

(aab,b)

(a,ab,b)

(a,a,b,b)

Among the good representations of w, the ones with the smallest number of elements are called the best representations of w.
For example, there are only one best representation of w=aabb: (aabb).

You are given a string w. Find the following:

the number of elements of a best representation of w

the number of the best representations of w, modulo 1000000007 \, (=10^9+7)

(It is guaranteed that a good representation of w always exists.)

Constraints

1 \leq |w| \leq 500000 \, (=5 \times 10^5)

w consists of lowercase letters (a-z).

Partial Score

400 points will be awarded for passing the test set satisfying 1 \leq |w| \leq 4000.

Input

The input is given from Standard Input in the following format:

w

Output

Print 2 lines.

In the first line, print the number of elements of a best representation of w.

In the second line, print the number of the best representations of w, modulo 1000000007.

Sample Input 1

aab

Sample Output 1

1
1

Sample Input 2

bcbc

Sample Output 2

2
3

In this case, there are 3 best representations of 2 elements:

(b,cbc)

(bc,bc)

(bcb,c)

Sample Input 3

ddd

Sample Output 3

3
1

Solution in C++ (GCC 5.4.1) (judge verdict: Accepted)

#include<bits/stdc++.h> 
using namespace std;
 
class Hash {
    public:
    
    Hash(const char *s, long long base = 1009, long long m = 1000000007) : MOD(m) {
        int n = strlen(s);
        
        hash = (long long *)malloc(sizeof(long long) * (n + 1));
        pow = (long long *)malloc(sizeof(long long) * (n + 1));
        
        hash[0] = 0;
        pow[0] = 1;
        
        for (int i = 0; i < n; i++) {
            hash[i + 1] = (hash[i] * base + s[i]) % MOD;
            pow[i + 1] = pow[i] * base % MOD;
        }
    }
    
    ~Hash() {
        free(hash);
        free(pow);
    }
    
    //x銇嬨倝y鏂囧瓧銇儚銉冦偡銉ュ€?
    long long get(int x, int y) {
        return (hash[x + y] - hash[x] * pow[y] % MOD + MOD) % MOD;
    }
    
    private:
    
    long long MOD;
    long long *hash;
    long long *pow;
};
 
char s[500001];
int b[500001];
vector <int> v[500001];
 
bool check(int x, int y, Hash &h1, Hash &h2) {
    int c = y - x, i, j;
    
    if (c == 1) return true;
    
    for (i = 0; i < v[c].size(); i++) {
        int z = (y - x) / v[c][i];
        
        for (j = 1; j * 2 <= v[c][i]; j *= 2) {
            if (h1.get(x, z * j) != h1.get(x + z * j, z * j)) break;
        }
        
        if (j * 2 <= v[c][i]) continue;
        
        if (h1.get(x, z * j) != h1.get(y - z * j, z * j)) continue;
        
        for (j = 1; j * 2 <= v[c][i]; j *= 2) {
            if (h2.get(x, z * j) != h2.get(x + z * j, z * j)) break;
        }
        
        if (j * 2 <= v[c][i]) continue;
        
        if (h2.get(x, z * j) != h2.get(y - z * j, z * j)) continue;
        
        return false;
    }
    
    return true;
}
 
int main() {
    int n, ans = 0, i;
    long long j;
    
    scanf("%s", s);
    
    n = strlen(s);
    
    for (i = 0; i < n; i++) {
        if (s[i] != s[0]) break;
    }
    
    if (i == n) {
        printf("%d\n", n);
        printf("%d\n", 1);
        
        return 0;
    }
    
    for (i = 2; i <= 500000; i++) {
        if (b[i] == 0) {
            b[i] = i;
            
            for (j = (long long)i * i; j <= 500000; j += i) {
                if (b[j] == 0) b[j] = i;
            }
        }
    }
    
    for (i = 1; i <= n; i++) {
        int c = i;
        
        while (c > 1) {
            if (v[i].size() == 0 || v[i].back() != b[c]) v[i].push_back(b[c]);
            
            c /= b[c];
        }
    }
    
    Hash h1(s);
    Hash h2(s, 10009, 1000000009);
    
    if (check(0, n, h1, h2) == true) {
        printf("%d\n", 1);
        printf("%d\n", 1);
        
        return 0;
    }
    
    for (i = 1; i < n; i++) {
        if (check(0, i, h1, h2) == true && check(i, n, h1, h2) == true) ans++;
    }
    
    printf("%d\n", 2);
    printf("%d\n", ans);
    
    return 0;
}