您的位置:首页 > 其它

【后缀数组】关于后缀数组模板的注解续

2015-04-06 11:33 288 查看
int wa
, wb
, ws
, wv

int rank
, height

#此处N比输入的N要多1,为人工添加的一个字符,用于避免CMP时越界
void getSA(int *r, int *sa, int n, int m)

int i, j, p, *x = wa, *y = wb, *t

# bucket清空
for(i = 0; i < m; i++) ws[i] = 0

#进行一次基数排序
for(i = 0; i < n; i++) ws[x[i] = r[i]]++
for(i = 1; i < m; i++) ws[i] += ws[i - 1]
for(i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i

#倍增法
for(j = 1, p = 1; p < n; j *= 2, m = p)

#string[n - j .. n] 是没有偏移为j的后缀 故第二关键字默认为0
#所以按照第二关键字排序肯定在最前面 同时还需要保证稳定性
for(p = 0, i = n - j; i < n; i++) y[p++] = i

#SA定义为'排第几的是谁' 根据第二关键字排序时
#第二关键字的次序就是其关联的第一关键字未完成排序时的次序
#所以SA[i] – j为按照第二关键字次序收集的未完成排序 的第一关键字序列
for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] – j

#这里的x是临时的RANK数组 y是等待排序的第一关键字下标数组(即第i后缀)
#映射出第一关键字之间的相对大小
for(i = 0; i < n; i++) wv[i] = x[y[i]]

#bucket清空
for(i = 0; i < m; i++) ws[i] = 0

#进行一次基数排序
for(i = 0; i < n; i++) ws[wv[i]]++
for(i = 1; i < m; i++) ws[i] += ws[i - 1]
for(i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]

#交换x y重标号临时SA
for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++

void getHeight(int *r, int *sa, int n)

int i, j, k = 0

#根据SA求RANK
for(i = 1; i <= n; i++) rank[sa[i]] = i

#利用性质 h[i] = height[rank[i]] 减少运算时间
#h[i] => height[rank[i]] => 表示第i后缀的height值
#第i后缀必然比第i-1后缀短 同时注意第i后缀 = 第i-1后缀剔除首字母
#记符号S(i)为原字符串的第i后缀
#记符号P(i)为第i后缀的SA值-1对应的后缀
#h[i]   = height[rank[i]]   => 第i后缀和第i后缀的SA值-1对应的后缀的LCP
#h[i-1] = height[rank[i-1]] => 第i-1后缀和第i-1后缀的SA值-1对应的后缀的LCP
#h[i] = LCP(S(i), P(i)) h[i - 1] = LCP(S(i - 1), P(i - 1))
#容易看出S(i - 1)剔除首字母后变为S(i)
#若h[i - 1] >= 1 则S(i - 1)和P(i - 1)的LCP >= 1
#P(i - 1)肯定是某个后缀 同时因为h[i - 1] >= 1 故strlen(P(i - 1)) >= 1
#所以P(i - 1)剔除首字母必然可以得到某个后缀
#同时由S(i - 1)剔除首字母可以得到S(i)和P(i)
#如果下标从1开始
#那么P(i - 1)和P(i)必然满足P(i - 1)[1 .. h[i - 1]] == P(i)[0 .. h[i - 1]]
#但P(i - 1)[h[i - 1] + 1 .. -1] 和 P(i)[h[i - 1] + 1 .. -1]不一定相等
#所以h[i] >= h[i - 1] - 1
#反之从0求h[i] 必然正确
#补充 height[i] = LCP(string[sa[i - 1] .. -1], string[sa[i] .. -1])
for(i = 0; i < n; height[rank[i++]] = k)
for(k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++)

char str

int sa

int main
char str

scanf("%s", str)
int n = strlen(str)
str
= 0

#注意区分此处为n+1,因为添加了一个结尾字符用于区别比较
getSA(str, sa, n + 1, 128)
getHeight(str, sa, n)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: