CSU-ACM2017暑期训练12-KMP G

来源:互联网 发布:网络用语dp什么意思 编辑:程序博客网 时间:2024/06/12 01:46

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

InputABACABAOutput31 43 27 1InputAAAOutput31 32 23 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 TESTfreopen("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;}
原创粉丝点击