【后缀数组】关于后缀数组模板的注解续
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)
相关文章推荐
- 【后缀数组】关于后缀数组模板的注解
- [sa][后缀数组]关于后缀数组的若干技巧
- 【后缀数组】后缀数组模板
- 后缀数组练习题bzoj 1031 后缀数组模板题目
- 后缀数组模板
- 【模板】后缀数组
- 后缀数组模板
- poj 3294(经典后缀数组模板)
- 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
- 后缀数组【模板】
- hdu 1403 Longest Common Substring (后缀数组模板题)
- 后缀数组_DC3(模板大全)
- 后缀数组模板
- 后缀数组 模板
- 后缀数组 模板
- cf244D. Match & Catch 字符串hash (模板)或 后缀数组。。。
- 后缀数组模板
- 后缀数组——附1(含模板)
- 关于网上搜查得到的3DC3的基于字符串后缀数组的排序方法的怀疑
- poj 2774 Long Long Message 后缀数组模板