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]);
}