432D Prefixes and Suffixes

题目大意

给你一个串

对于一个子串如果它既是前缀又是后缀

输出它的长度以及它在原串中一共出现了多少次

分析

对于既是前缀又是后缀的判断和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;
}
上一篇:UOJ#58. 【WC2013】糖果公园


下一篇:P3953 逛公园