CSU-ACM2017暑期訓練12-KMP G - Next[]樹 CodeForces - 432D

G - Next[]樹 CodeForces - 432D

You have a string s = s1s2...s|s|, where |s| is the length of string s, and si its i-th character.

Let's introduce several definitions:

    A substring s[i..j] (1 ≤ i ≤ j ≤ |s|) of string s is string sisi + 1...sj.
    The prefix of string s of length l (1 ≤ l ≤ |s|) is string s[1..l].
    The suffix of string s of length l (1 ≤ l ≤ |s|) is string s[|s| - l + 1..|s|].

Your task is, for any prefix of string s which matches a suffix of string s, print the number of times it occurs in string s as a substring.

Input

The single line contains a sequence of characters s1s2...s|s| (1 ≤ |s| ≤ 105) — string s. The string only consists of uppercase English letters.

Output

In the first line, print integer k (0 ≤ k ≤ |s|) — the number of prefixes that match a suffix of string s. Next print k lines, in each line print two integers li ci. Numbers li ci mean that the prefix of the length li matches the suffix of length li and occurs in string s as a substring ci times. Print pairs li ci in the order of increasing li.

Example

Input

ABACABA

Output

3
1 4
3 2
7 1




Input

AAA

Output

3
1 3
2 2
3 1
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1e5+10;

char s[maxn];
int Next[maxn], saveLen[maxn], occurrence[maxn], num[maxn];

void getNext(){
    int len = strlen(s);
    int j;
    Next[0] = Next[1] = 0;
    for(int i = 1; i < len; i++){
        j = Next[i];
        while(j && s[i] != s[j])
            j = Next[j];
        if(s[i] == s[j])
            Next[i + 1] = j + 1;
        else
            Next[i + 1] = 0;
    }
}

int main(){
#ifdef TEST
freopen("test.txt", "r", stdin);
#endif // TEST

    while(scanf("%s", s) != EOF){
        getNext();
        int cnt = 0, len = strlen(s);
        for(int i = 0; i <= len; i++)
            occurrence[i] = 1;
        for(int i = len; i >= 1; i--)
            occurrence[Next[i]] += occurrence[i];
        int temp = len;
        while(temp){
            num[cnt] = occurrence[temp];
            saveLen[cnt] = temp;
            cnt++;
            temp = Next[temp];
        }
        cout << cnt << endl;
        for(int i = cnt - 1; i >= 0; i--)
            cout << saveLen[i] << " " << num[i] << endl;
    }

    return 0;
}
發佈了68 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章