请高手分析一下算法原理
xenix 2003-07-20 02:04:17 //这是 Lucent 的 suffix sort的c实现,但小弟看不懂原理,请高手帮忙讲解一下
#include <stdlib.h>
enum {
ORIG = ~(~0u>>1), /* sign bit */
BUCK = ~(~0u>>1)
};
void shared(int a[], int n, int p[], int q[], int s[], int h);
#define pred(i, h) ((t=(i)-(h))<0? t+n: t)
#define succ(i, h) ((t=(i)+(h))>=n? t-n: t)
int
ssort(int a[], int s[])
{
int h, i, j, l, n, t;
int k = 0; /* initialized for lint */
int *p = 0;
int result = 0;
int *q = 0;
# define al a
# define pl p
# define finish(r) if(1){result=r; goto out;}else
for(j=n=0; a[n]>0; n++) /* find n */
if(a[n] > j)
j = a[n]; /* and max element */
if(a[n++]<0 || j>=n)
finish(2);
p = malloc(n*sizeof(int));
if(p == 0)
finish(1);
for(i=0; i<n; i++) /* (0) initialize */
p[i] = i | ORIG;
if(s) { /* shared lengths */
q = malloc(n*sizeof(int));
if(q == 0)
finish(1);
}
for(h = 0; ; h = h==0? 1: 2*h) {
for(i=0; i<n; i++) { /* (1) link */
for(j=p[i]; !(j&ORIG); j=al[j]);
j = pred(j&~ORIG, h);
l = a[j];
al[j] = pl[l];
pl[l] = j;
}
if(h == 0) { /* find k */
for(k=0; k<n; k++)
if(pl[k]&ORIG)
break;
for(i=k; i<n; i++) /* check input */
if(!(pl[i]&ORIG))
finish(2);
}
for(i=n; --k>=0; ) { /* (2) order */
j = pl[k];
do
p[--i] = j;
while(!((j=al[j]) & ORIG));
p[i] |= BUCK;
}
for(i=0; i<n; i++) { /* (3) reconstruct */
if(p[i] & BUCK)
k++;
a[p[i]&~BUCK] = k;
}
for(i=0, j=-1; i<n; i++, j=l) { /* (4) refine */
l = a[succ(p[i]&~BUCK, h)];
if(l != j)
p[i] |= BUCK;
}
if(s)
shared(a, n, p, q, s, h);
for(i=0, k=-1; i<n; i++) { /* (5) recode */
if(p[i] & BUCK)
k++;
a[p[i]&~BUCK] = k;
p[i] |= ORIG; /* (0b) reinitialize */
}
if(++k >= n)
break;
}
for(i=0; i<n; i++)
a[i] = p[i] & ~ORIG;
out:
free(p);
free(q);
return result;
}
void
shared(int a[], int n, int p[], int q[], int s[], int h)
{
int i, j, k0, k1, t, u;
if(h == 0) { /* (0) initialize */
for(i=0; i<n; i++)
if(p[i]&BUCK)
q[i] = s[i] = 0;
else
q[i] = -1;
return;
}
for(i=j=0; i<n; i++) { /* (1) get parents */
if(q[i] >= 0)
j = i;
a[p[i]&~BUCK] = j;
}
for(i=0; i<n; i++) { /* (2) find lengths */
if(!(p[i]&BUCK))
continue;
k0 = j; /* k0=garbage if i=0 */
k1 = j = a[succ(p[i]&~BUCK, h)];
if(q[i] >= 0)
continue;
for(u=n; k1>k0; k1=q[k1])
if(s[k1] < u)
u = s[k1];
s[i] = h + u;
}
for(i=0; i<n; i++) /* (3) update tree */
if(p[i]&BUCK) {
if(q[i] < 0)
for(t=j; ;t=q[t]) {
q[i] = t;
if(s[i] > s[t])
break;
}
j = i;
}
}