后缀数组模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void get_sa(int n)
{
int m=127;
for(int i=1;i<=n;i++) Rank[i]=str[i],tp[i]=i;
for(int i=0;i<=m;i++) sum[i]=0;
for(int i=1;i<=n;i++) sum[Rank[tp[i]]]++;
for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
for(int i=n;i>=1;i--) sa[sum[Rank[tp[i]]]--]=tp[i];
int p=1;
for(int len=1;p<n;m=p,len<<=1)
{
p=0;
for(int i=n-len+1;i<=n;i++) tp[++p]=i;
for(int i=1;i<=n;i++) if(sa[i]>len) tp[++p]=sa[i]-len;
for(int i=0;i<=m;i++) sum[i]=0;
for(int i=1;i<=n;i++) sum[Rank[tp[i]]]++;
for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
for(int i=n;i>=1;i--) sa[sum[Rank[tp[i]]]--]=tp[i];
swap(Rank,tp);
Rank[sa[1]]=1;
p=1;
for(int i=2;i<=n;i++)
Rank[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+len]==tp[sa[i-1]+len])?p:++p;
}
int _lst=0,j;
for(int i=1;i<=n;height[Rank[i++]]=_lst) // i -> lpos
for(_lst=_lst?_lst-1:_lst,j=sa[Rank[i]-1];str[j+_lst]==str[i+_lst];_lst++);
}
void get_st(int n)
{
for(int i=2;i<=n;i++)
lg2[i]=lg2[i>>1]+1;
for(int i=1;i<=n;i++)
st[i][0]=height[i];
for(int j=1;j<=lg2[n];j++)
for(int i=1;i<=n&&i+(1<<(j-1))<=n;i++)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int query(int l,int r) //l,r => Rank
{
if(l>r) swap(l,r);
++l; //notice
int len=lg2[r-l+1];
//printf("%d %d %d %d %d\n",l,r,st[l][len],st[r-(1<<len)+1][len],len);
return min(st[l][len],st[r-(1<<len)+1][len]);
}