https://www.luogu.org/problemnew/show/SP8222#sub
http://www.spoj.com/problems/NSUBSTR/
翻译来自洛谷。
你得到一个字符串,最多由25万个小写拉丁字母组成。我们将 F(x)定义为某些长度X的字符串在s中出现的最大次数,例如字符串‘ababaf‘- F(x),因为有一个字符串‘ABA‘出现两次。你的任务是输出 F(x)每一个I,以使1<=i<=|S|.
water!
后缀自动机后对l排个序,对每个l更新其ans就做完了。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cctype> using namespace std; typedef long long ll; const int N=500005; struct tree{ int a[26],fa,l; }tr[N]; char s[N]; int last,cnt,ans[N]; int a[N],w[N],size[N]; inline void insert(int c){ int p=last,np=++cnt; last=np;tr[np].l=tr[p].l+1; for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np; if(!p)tr[np].fa=1; else{ int q=tr[p].a[c]; if(tr[p].l+1==tr[q].l)tr[np].fa=q; else{ int nq=++cnt;tr[nq].l=tr[p].l+1; memcpy(tr[nq].a,tr[q].a,sizeof(tr[q].a)); tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq; for(;p&&tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq; } } size[np]=1; } int main(){ scanf("%s",s); int len=strlen(s); last=cnt=1; for(int i=0;i<len;i++)insert(s[i]-‘a‘); for(int i=1;i<=cnt;i++)w[tr[i].l]++; for(int i=1;i<=len;i++)w[i]+=w[i-1]; for(int i=1;i<=cnt;i++)a[w[tr[i].l]--]=i; for(int i=cnt;i>=1;i--){ size[tr[a[i]].fa]+=size[a[i]]; ans[tr[a[i]].l]=max(ans[tr[a[i]].l],size[a[i]]); } for(int i=1;i<=len;i++)printf("%d\n",ans[i]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
原文地址:https://www.cnblogs.com/luyouqi233/p/8776312.html
时间: 2024-11-10 13:27:22