1. 程式人生 > >Jzoj5462【NOIP2017提高A組衝刺11.8】好文章

Jzoj5462【NOIP2017提高A組衝刺11.8】好文章

nodgd寫了一篇文章,自認為這是一篇好文章。nodgd的文章由n個小寫英文字母組成。文章的一個子串指的是文章中的一段連續的字母,子串的長度就是這一段的字母個數。nodgd在文章中用了排比、對偶、前後照應之類的手法,所以就有很多個子串是相同或者相近的。為了向大家證明這是一篇好文章,nodgd決定給自己的文章進行評分。nodgd首先確定了一個整數m,然後統計出文章中有多少個不相同的長度為m的子串,這個數量就是文章的評分。
然而,nodgd懶得老老實實計算這個評分了,就把任務丟給了你。

這個題卡雜湊,要麼用雙雜湊,還是sam比較穩'233333',雜湊就是拿來對拍的

#include<stdio.h>
#include<string.h> #include<algorithm> #define N 400010 using namespace std; char str[N]; int s[N][26],mx[N],sz[N],f[N]; int cnt=1,lst=1,r[N],v[N],n,m,ans=0; int extend(char c){ int p=lst,np=lst=++cnt,q,nq; c-='a'; mx[np]=mx[p]+1; for(;p&&!s[p][c];p=f[p]) s[p][c]=np; if(!p) return
f[np]=1; q=s[p][c]; if(mx[q]==mx[p]+1) f[np]=q; else { nq=++cnt; mx[nq]=mx[p]+1; f[nq]=f[q]; f[q]=f[np]=nq; memcpy(s[nq],s[q],26<<2); for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq; } } int main(){ freopen("article.in","r",stdin); freopen("article.out","w",stdout); scanf("%d%d%s"
,&n,&m,str+1); for(int i=1;i<=n;++i) extend(str[i]); for(int i=1;i<=cnt;++i) ++v[mx[i]]; for(int i=1;i<=n;++i) v[i]+=v[i-1]; for(int i=cnt;i;--i) r[v[mx[i]]--]=i; for(int p,i=cnt;i;--i){ p=r[i]; if(mx[p]>=m && mx[f[p]]<m) ans++; } printf("%d\n",ans); }