[UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]

后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法

具体解释详见2009年国家集训队论文

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cmath>
 7 #include <ctime>
 8 
 9 using namespace std;
10 
11 int    str[110000];
12 int    Barrel[2][110000],U[110000],Tmp[110000],SA[110000],H[110000];
13 char    r[110000];
14 
15 void    Calc_H(const int & n,const int * Rank)
16 {
17     int    i,j,k=0;
18     for(i=0;i<n;H[Rank[i++]]=k)
19         for(k?k--:0,j=SA[Rank[i]-1];str[i+k]==str[j+k];++k);
20     return ;
21 }
22 
23 bool    cmp(const int * s,const int a,const int b,const int l)
24 {
25     return s[a]==s[b] && s[a+l]==s[b+l];
26 }
27 
28 int*    Get_SA(const int & n,int  m)
29 {
30     int    i,j,p,*x=Barrel[0],*y=Barrel[1];
31     memset(U,0,sizeof(U));
32     for(i=0;i<n;++i)U[x[i]=str[i]]++;
33     for(i=1;i<m;++i)U[i]+=U[i-1];
34     for(i=n-1;i>=0;--i)SA[--U[x[i]]]=i;
35 
36     for(j=1,p=1;p<n;j<<=1,m=p)
37     {
38         for(p=0,i=n-j;i<n;++i)y[p++]=i;
39         for(i=0;i<n;++i)if(SA[i]>=j)y[p++]=SA[i]-j;
40         for(i=0;i<n;++i)Tmp[i]=x[y[i]];
41         for(i=0;i<m;++i)U[i]=0;
42         for(i=0;i<n;++i)U[Tmp[i]]++;
43         for(i=1;i<m;++i)U[i]+=U[i-1];
44         for(i=n-1;i>=0;--i)SA[--U[Tmp[i]]]=y[i];
45         for(swap(x,y),p=1,x[SA[0]]=0,i=1;i<n;++i)
46         x[SA[i]]=cmp(y,SA[i-1],SA[i],j)?p-1:p++;
47     }
48     Calc_H(n,x);
49     return x;
50 }
51 
52 int main()
53 {
54     int    i,n;
55     scanf("%s",r);
56     n=strlen(r);
57     for(i=0;i<n;++i)str[i]=r[i];
58 
59     Get_SA(n+1,256);
60 
61     for(i=1;i<=n;++i)printf("%d ",SA[i]+1);
62     printf("
");
63     for(i=2;i<=n;++i)printf("%d ",H[i]);
64     
65     return 0;
66 }
View Code

在计算H数组的时候因为在计算SA数组的程序中x所代表的数组中就是Rank数组,所以不需要重新计算