后缀数组构造

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 }
View Code

  后缀数组和后缀自动机一样,还是很有用的。不会打SA或SAM遇到字符串必定会挂。

以上是关于后缀数组构造的主要内容,如果未能解决你的问题,请参考以下文章

后缀自动机总结

字符串-后缀数组

后缀数组入门

后缀数组

后缀数组

在 Visual Studio 中创建构造函数的代码片段或快捷方式