裸的统计不同的重复出现子串(不重叠)种数的题。多次使用后缀排序要注意小细节。y数组在重复使用时一定要清空,看那个line25 +k就明白了 ,cnt也要清空,为什么就不说了
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 5 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 6 const int N=1000+7; 7 char s[N]; 8 int n,m; 9 ll ans; 10 11 int sa[N],rk[N],x[N],y[N],cnt[N],h[N],p; 12 inline void build(){ 13 memset(cnt,0,sizeof cnt);memset(y,0,sizeof y);// 14 for(register int i=1;i<=n;++i)++cnt[x[i]=s[i]]; 15 for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1]; 16 for(register int i=n;i;--i)sa[cnt[x[i]]--]=i; 17 for(register int k=1;k<n;k<<=1,p=0){ 18 for(register int i=n-k+1;i<=n;++i)y[++p]=i; 19 for(register int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k; 20 for(register int i=1;i<=m;++i)cnt[i]=0; 21 for(register int i=1;i<=n;++i)++cnt[x[y[i]]]; 22 for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1]; 23 for(register int i=n;i;--i)sa[cnt[x[y[i]]]--]=y[i]; 24 swap(x,y);x[sa[1]]=p=1; 25 for(register int i=2;i<=n;++i)x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p; 26 if(p==n)break; m=p; 27 }p=0; 28 // for(register int i=1;i<=n;++i)printf("%d %d\n",i,x[i]); 29 for(register int i=1;i<=n;h[x[i]]=p,p?--p:1,++i)while(s[i+p]==s[sa[x[i]-1]+p]&&++p); 30 } 31 32 inline void search(int k){ 33 int l=sa[1],r=sa[1]; 34 for(register int i=2;i<=n;++i){ 35 if(h[i]<k){r-l>=k?++ans:1;l=r=sa[i];} 36 MIN(l,sa[i]),MAX(r,sa[i]); 37 } 38 r-l>=k?++ans:1; 39 } 40 41 int main(){ 42 while(~scanf("%s",s+1)){ 43 if(s[1]==‘#‘)break; 44 n=strlen(s+1),m=127,ans=0,p=0,build(); 45 for(register int i=1;i<=n/2;++i)search(i); 46 printf("%lld\n",ans); 47 } 48 return 0; 49 }
原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10340292.html
时间: 2024-11-12 08:20:46