hdu3518 Boring Counting[后缀排序]

裸的统计不同的重复出现子串(不重叠)种数的题。
多次使用后缀排序要注意小细节。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
",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
",ans);
47     }
48     return 0;
49 }




原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10340292.html