题目大意
给你一个串
对于一个子串如果它既是前缀又是后缀
输出它的长度以及它在原串中一共出现了多少次
分析
对于既是前缀又是后缀的判断和126B相同
然后我们只需要记录每个不同的z[i]出现了多少次
然后对于每个合法z[i]输出所有大于z[i]的数的出现次数即可
因为如果长度为z[i]的前缀是最长前缀
那么小于z[i]的前缀一定合法
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
char s[100100];
int n,z[100100],sum[100100],cnt,ans[100100];
inline void get_z(){
int i,j,k,l=0,r=0;
for(i=1;i<n;i++){
if(i<=r)z[i]=min(r-i+1,z[i-l]);
while(i+z[i]<n&&s[z[i]]==s[z[i]+i])z[i]++;
if(i+z[i]-1>r)r=i+z[i]-1,l=i;
}
}
int main(){
int i,j,k;
scanf("%s",s);
n=strlen(s);
get_z();
for(i=1;i<n;i++){
sum[z[i]]++;
if(z[i]==n-i)ans[++cnt]=z[i];
}
printf("%d
",cnt+1);
sort(ans+1,ans+cnt+1);
for(i=n-1;i>0;i--)sum[i]+=sum[i+1];
for(i=1;i<=cnt;i++)printf("%d %d
",ans[i],sum[ans[i]]+1);
printf("%d %d
",n,1);
return 0;
}