后缀数组构造
Posted voyage~st~Imagine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀数组构造相关的知识,希望对你有一定的参考价值。
读了罗穗的论文,终于知道后缀数组怎么构造了,还反复打了五遍,打得很痛苦才最终理解。
终于体会到XY的痛苦了。实在是一篇OI生涯中最难懂的代码orz看来两天。一下是经过稍微加长的稍微易理解的代码(其实差不多好吧)。
具体注释看 网址
1 #include<cstdio> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 6 struct suffix_array 7 { 8 const long N; 9 long *sa,*sa2,*hgt,*rk,n; 10 char *str; 11 suffix_array(long maxn=10000):N(maxn) 12 { 13 str=new char[N]; 14 sa=new long[N],sa2=new long[N],hgt=new long[N],rk=new long[N]; 15 } 16 17 bool same(long *rank,long id1,long id2,long len) 18 { 19 return rank[id1]==rank[id2]&&rank[id1+len]==rank[id2+len]; 20 } 21 void make_sa() 22 { 23 long *cnt,m,i,len,p; 24 cnt=new long[N+26]; 25 memset(cnt,0,sizeof(long)*(N+26)); 26 for (i=0;i<n;i++){ 27 cnt[rk[i]=str[i]-\'a\']++; 28 m=(rk[i]>m)?rk[i]:m; 29 } 30 m++; 31 for (i=1;i<m;i++)cnt[i]+=cnt[i-1]; 32 for (i=0;i<n;i++)sa[--cnt[rk[i]]]=i; 33 34 for (len=1;len<n;len*=2){ 35 for (i=n-len,p=0;i<n;i++)sa2[p++]=i; 36 for (i=0;i<n;i++) 37 if (sa[i]>=len)sa2[p++]=sa[i]-len; 38 39 memset(cnt,0,sizeof(long)*m); 40 for (i=0;i<n;i++)cnt[rk[i]]++; 41 for (i=1;i<m;i++)cnt[i]+=cnt[i-1]; 42 for (i=0;i<n;i++)sa[--cnt[rk[sa2[i]]]]=sa2[i]; 43 44 swap(rk,sa2); 45 rk[sa[0]]=0; 46 for (i=1;i<n;i++){ 47 rk[sa[i]]=rk[sa[i-1]]; 48 if (!same(sa2,i,i-1,len))rk[sa[i]]++; 49 } 50 m=rk[sa[n-1]]+1; 51 if (m==n)break; 52 } 53 } 54 55 void make_hgt() 56 { 57 long i,j,lcp; 58 for (i=0,lcp=0;i<n-1;i++){ 59 if (lcp>0)lcp--; 60 j=sa[rk[i]-1]; 61 while (str[j+lcp]==str[i+lcp])lcp++; 62 hgt[rk[i]]=lcp; 63 } 64 } 65 66 void Build(char *s) 67 { 68 n=strlen(s); 69 memcpy(str,s,sizeof(n)); 70 make_sa(); 71 make_hgt(); 72 } 73 }; 74 75 int main() 76 { 77 suffix_array SA(10000); 78 return 0; 79 }
后缀数组和后缀自动机一样,还是很有用的。不会打SA或SAM遇到字符串必定会挂。
以上是关于后缀数组构造的主要内容,如果未能解决你的问题,请参考以下文章