题目大意
给你一个串
对于一个子串如果它既是前缀又是后缀
输出它的长度以及它在原串中一共出现了多少次
分析
对于既是前缀又是后缀的判断和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\n",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\n",ans[i],sum[ans[i]]+1); printf("%d %d\n",n,1); return 0; }