- SA 按顺序排列。
- ranks指出了每一个位置的排名。
#define maxn 200010
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int Ra[maxn], Rb[maxn], Rv[maxn], Rs[maxn];
int c0(int r[], int a, int b){
return r[a]==r[b] && r[a+1]==r[b+1] && r[a+2]==r[b+2];
}
int c12(int k, int r[], int a, int b){
if(k==2)
return r[a]<r[b] || (r[a]==r[b] && c12(1,r,a+1,b+1));
else
return r[a]<r[b] || (r[a]==r[b] && Rv[a+1]<Rv[b+1]);
}
void Rsort(int r[], int a[], int b[], int n, int m){
int i;
for(i = 0; i < n; ++i) Rv[i] = r[a[i]];
for(i = 0; i < m; ++i) Rs[i] = 0;
for(i = 0; i < n; ++i) ++Rs[Rv[i]];
for(i = 1; i < m; ++i) Rs[i] += Rs[i-1];
for(i = n-1; i >= 0; --i) b[--Rs[Rv[i]]] = a[i];
}
void dc3(int r[], int sa[], int n, int m){
int i, j, *rn = r+n, *san = sa+n, ta=0, tb=(n+1)/3, tbc=0, p;
r[n] = r[n+1] = 0;
for(i = 0; i < n; ++i)
if(i%3!=0) Ra[tbc++] = i;
Rsort(r+2, Ra, Rb, tbc, m);
Rsort(r+1, Rb, Ra, tbc, m);
Rsort(r, Ra, Rb, tbc, m);
rn[F(Rb[0])] = 0; p = 1;
for(i = 1; i < tbc ; ++i)
rn[F(Rb[i])] = c0(r, Rb[i-1], Rb[i]) ? p-1 : p++;
if(p < tbc)
dc3(rn, san, tbc, p);
else
for(i=0;i<tbc;i++)
san[rn[i]] = i;
for(i = 0; i < tbc; ++i)
if(san[i]<tb)
Rb[ta++] = san[i]*3;
if(n%3==1)
Rb[ta++]=n-1;
Rsort(r, Rb, Ra, ta, m);
for(i = 0; i < tbc; ++i)
Rv[Rb[i] = G(san[i])] = i;
for(i=0,j=0,p=0; i<ta && j<tbc; p++)
sa[p] = c12(Rb[j]%3, r, Ra[i], Rb[j]) ? Ra[i++] : Rb[j++];
while(i < ta)
sa[p++] = Ra[i++];
while(j < tbc)
sa[p++] = Rb[j++];
}
int ranks[maxn], height[maxn];
void calheight(int r[], int sa[], int n){
int i, j, k = 0;
for(i = 1; i <= n; ++i)
ranks[sa[i]] = i;
for(i = 0; i < n; height[ranks[i++]] = k){
k ? k-- : 0; j = sa[ranks[i]-1];
while(r[i+k]==r[j+k])
++k;
}
}
char st[maxn];
int source[maxn*3], sa[maxn*3];