码迷,mamicode.com
首页 > 编程语言 > 详细

后缀数组构造

时间:2017-08-20 22:38:45      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:opened   none   bre   pre   closed   array   技术分享   span   names   

  读了罗穗的论文,终于知道后缀数组怎么构造了,还反复打了五遍,打得很痛苦才最终理解。

  终于体会到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遇到字符串必定会挂。

后缀数组构造

标签:opened   none   bre   pre   closed   array   技术分享   span   names   

原文地址:http://www.cnblogs.com/live-no-regrets/p/7401564.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!