Codeforces 432D-Prefixes and Suffixes
Posted qjy73
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 432D-Prefixes and Suffixes相关的知识,希望对你有一定的参考价值。
传送门:Codeforces 432D-Prefixes and Suffixes
题意
给定一个字符串,找出其所有相同的前缀和后缀,每行打印两个数字a,b,表示前缀(后缀)的长度,以及它在字符串中出现的次数。
题解
前置知识:统计每个前缀在原字符串中出现的次数。
考虑位置(i)的前缀函数值(nxt[i])。根据定义,其意味着字符串(s)一个长度为(nxt[i])的前缀在位置(i)出现并以(i) 为右端点,同时不存在一个更长的前缀满足前述定义。与此同时,更短的前缀可能以该位置为右端点。容易看出,我们遇到了在计算前缀函数时已经回答过的问题:给定一个长度为(j)的前缀,同时其也是一个右端点位于(i)的后缀,下一个更小的前缀长度(k< j)是多少?该长度的前缀需同时也是一个右端点为(i)的后缀。因此以位置(i)为右端点,有长度为(nxt[i])的前缀,有长度为(nxt[nxt[i]-1])的前缀,有长度为(nxt[nxt[nxt[i]-1]-1])的前缀,等等,直到长度变为0。故而我们可以通过下述方式计算答案。
vector<int> ans(n + 1);
for (int i = 0; i < n; i++) ans[nxt[i]]++;
for (int i = n - 1; i > 0; i--) ans[nxt[i - 1]] += ans[i];
for (int i = 0; i <= n; i++) ans[i]++;
(参见OI-wiki)
预处理出每个前缀出现的次数,字符串所有相等的前缀和后缀可以通过不断地nxt获得。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
const int N=1e5+10;
char a[N];
int nxt[N],cnt[N];
struct node{
int pos,num;
}ans[N];
int tot;
int la;
void getnxt(char *p){
nxt[0]=0;
for(int i=1;i<la;i++){
int j=nxt[i-1];
while(j>0&&p[i]!=p[j]) j=nxt[j-1];
if(p[i]==p[j]) j++;
nxt[i]=j;
}
}
void solve(){
for(int i=0;i<la;i++) cnt[nxt[i]]++;
for(int i=la-1;i>=0;i--) cnt[nxt[i-1]]+=cnt[i];
for(int i=0;i<=la;i++) cnt[i]++;
}
bool cmp(node a,node b){
return a.pos<b.pos;
}
int main(){
scanf("%s",a);
la=strlen(a);
getnxt(a);
solve();
int now=la;
while(now){
ans[++tot].pos=now;
ans[tot].num=cnt[now];
now=nxt[now-1];
}
sort(ans+1,ans+1+tot,cmp);
printf("%d
",tot);
for(int i=1;i<=tot;i++){
printf("%d %d
",ans[i].pos,ans[i].num);
}
return 0;
}
以上是关于Codeforces 432D-Prefixes and Suffixes的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 432D Prefixes and Suffixes
Codeforces 432D Prefixes and Suffixes (KMP后缀数组)