Prefixes and Suffixes

题面

题目描述

给你一个字符串s,对于s的每一个前缀,如果它也是s的一个后缀,输出这个前缀在s中出现了多少次。

输入格式

一个字符串s(长度<=100000);只含有大写字母。

输出格式

第一行输出一个整数k——满足条件的前缀个数;
接下来k行,每行两个整数l,c,代表长度为l的前缀满足条件,在整个字符串中出现了c次。按l从小到大输出。

样例

Input1

ABACABA

Output1

3
1 4
3 2
7 1

Input2

AAA

Output2

3
1 3
2 2
3 1

题解

考虑每一个前缀\(str[0 .. i]\), 假如它也是字符串的后缀的话, 则有\(str[len - i - 1 .. len - 1] = str[0 .. i]\), 即\(match[len - i - 1] = i\).
对于每一个\(i\)判断是否存在\(match[len - i - 1] = i\)即可, 并统计整个\(match[]\)数组中\(match[n] >= i\)的数量即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
 
const int L = (int)1e5;
 
int main()
{
    static char str[L];
    scanf("%s", str);
    int len = strlen(str);
    static int mch[L];
    mch[0] = len - 1, mch[1] = -1;
    for(; mch[1] + 1 < len && str[mch[1] + 1] == str[1 + mch[1] + 1]; ++ mch[1]);
    int p = 1, mx = p + mch[p];
    for(int i = 2; i < len; ++ i)
    {
        mch[i] = std::max(std::min(mx - i, mch[i - p]), -1);
        for(; i + mch[i] < len && str[mch[i] + 1] == str[i + mch[i] + 1]; ++ mch[i]);
        if(i + mch[i] > mx)
            p = i, mx = i + mch[i];
    }
    static int sum[L];
    memset(sum, 0, sizeof(sum));
    for(int i = 0; i < len; ++ i)
        if(~ mch[i])
            ++ sum[mch[i]];
    for(int i = len - 1; i; -- i)
        sum[i - 1] += sum[i];
    int cnt = 0;
    for(int i = 0; i < len; ++ i)
        if(mch[len - i - 1] == i)
            ++ cnt;
    printf("%d\n", cnt);
    for(int i = 0; i < len; ++ i)
        if(mch[len - i - 1] == i)
            printf("%d %d\n", i + 1, sum[i]);
}
posted @ 2017-07-06 09:37  Zeonfai  阅读(336)  评论(0编辑  收藏  举报