现在来看倍增算法是非常好理解的。
直接放一篇blog写的挺好的:http://www.cnblogs.com/zinthos/p/3899725.html
虽然理论复杂度是$O(nlogn)$,但其中各种细节优化确实十分有必要的。
给自己放一个倍增的模板,有空填DC3的坑
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int n,m; 6 char s[1000010]; 7 int rk[1000010],sa[1000010],tmp[1000010],c[1000010]; 8 void outint(int x){ 9 if(x>=10) outint(x/10); 10 putchar(x%10+‘0‘); 11 } 12 bool inline cmp(int *r,int a,int b,int l){ 13 return r[a]==r[b]&&r[a+l]==r[b+l]; 14 } 15 void Getsa(){ 16 m=127; 17 for(int i=0;i<=m;i++) c[i]=0; 18 for(int i=1;i<=n;i++) c[rk[i]=s[i]]++; 19 for(int i=1;i<=m;i++) c[i]+=c[i-1]; 20 for(int i=n;i>=1;i--) sa[c[rk[i]]--]=i; 21 for(int i=1;i<=n;i<<=1){ 22 int p=0; 23 for(int j=n-i+1;j<=n;j++) tmp[++p]=j; 24 for(int j=1;j<=n;j++) if(sa[j]>i) tmp[++p]=sa[j]-i; 25 for(int j=0;j<=m;j++) c[j]=0; 26 for(int j=1;j<=n;j++) c[rk[tmp[j]]]++; 27 for(int j=1;j<=m;j++) c[j]+=c[j-1]; 28 for(int j=n;j>=1;j--) sa[c[rk[tmp[j]]]--]=tmp[j]; 29 swap(rk,tmp); 30 rk[sa[1]]=p=1; 31 for(int j=2;j<=n;j++) rk[sa[j]]=cmp(tmp,sa[j],sa[j-1],i)?p:++p; 32 if(p>=n) break; 33 m=p; 34 } 35 } 36 int main(){ 37 scanf("%s",s+1); 38 n=strlen(s+1); 39 Getsa(); 40 for(int i=1;i<=n;i++){ 41 outint(sa[i]); 42 putchar(‘ ‘); 43 } 44 return 0; 45 }
时间: 2024-10-26 00:03:11