后缀数组倍增算法模板详解
来源:互联网 发布:mac 安装oracle数据库 编辑:程序博客网 时间:2024/05/01 10:41
参考
2009国家集训队论文 后缀数组——处理字符串的有力工具 ——罗穗骞
模板
bool cmp(int* r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; }void init(int* r, int* sa, int n, int m) { int* x=wa, *y=wb, *t, i, j, p; for (i = 0; i < m; ++i) wt[i] = 0; for (i = 0; i < n; ++i) ++wt[x[i] = r[i]]; for (i = 1; i < m; ++i) wt[i] += wt[i - 1]; for (i = n-1; i >= 0; --i) sa[--wt[x[i]]] = i; for (j = 1, p = 1; p < n; j <<= 1, m = p) { //注意!每次循环要记得更新m的值! for (p = 0, i = n-j; i < n; ++i) y[p++] = i; for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i < n; ++i) wv[i] = x[y[i]]; for (i = 0; i < m; ++i) wt[i] = 0; for (i = 0; i < n; ++i) ++wt[wv[i]]; for (i = 1; i < m; ++i) wt[i] += wt[i - 1]; for (i = n-1; i >= 0; --i) sa[--wt[wv[i]]] = y[i]; t = x, x = y, y = t, x[sa[0]] = 0; for (p = 1, i = 1; i < n; ++i) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? p - 1 : p++; } for (i = 0; i < n; ++i) rk[sa[i]] = i; int k = 0; for (i = 0; i < n - 1; h[rk[i++]] = k) { //注意!这里上界是n-1而不是n,因为sa[n-1] = 0 for (k = k ? --k : 0, j = sa[rk[i] - 1]; r[i+k] == r[j+k]; ++k); }}
解释
请在理解了算法的基础上食用
参数
void init(int* r, int* sa, int n, int m);
第一部分
for (i = 0; i < m; ++i) wt[i] = 0; for (i = 0; i < n; ++i) ++wt[x[i] = r[i]]; for (i = 1; i < m; ++i) wt[i] += wt[i - 1]; for (i = n-1; i >= 0; --i) sa[--wt[x[i]]] = i;
第二部分
循环体
for (j = 1, p = 1; p < n; j <<= 1, m = p) { //注意!每次循环要记得更新m的值!
当某一次循环结束后所有排名都不相同即可停止,即名次数等于
计数排序的上限
循环体内
- 1.
for (p = 0, i = n-j; i < n; ++i) y[p++] = i; for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
我们知道,倍增算法的主要思想是基数排序,在这里,基数排序有两个关键字。
即
具体操作上:
显然对于字符串的最后
再从头到尾遍历一遍,将
- 2.
for (i = 0; i < n; ++i) wv[i] = x[y[i]];
由此,我们得出,
3.
for (i = 0; i < m; ++i) wt[i] = 0; for (i = 0; i < n; ++i) ++wt[wv[i]]; for (i = 1; i < m; ++i) wt[i] += wt[i - 1]; for (i = n-1; i >= 0; --i) sa[--wt[wv[i]]] = y[i];
再做一遍计数排序,使得在第二关键字升序的基础上,第一关键字也升序,将下标一个个填进去。
4.
t = x, x = y, y = t, x[sa[0]] = 0; for (p = 1, i = 1; i < n; ++i, ++p) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? p - 1 : p;
因为
因为可能有相同的字符串,所以并不是单纯的逆运算,还需要用
bool cmp(int* r, int a, int b, int l) { return r[a] == r[b] && r[a+l] == r[b+l]; }
只需比较第一关键字和第二关键字即可。(注意,这里的
第三部分
for (i = 0; i < n; ++i) rk[sa[i]] = i; int k = 0; for (i = 0; i < n - 1; h[rk[i++]] = k) { //注意!这里上界是n-1而不是n,因为sa[n-1] = 0 for (k = k ? --k : 0, j = sa[rk[i] - 1]; r[i+k] == r[j+k]; ++k); }
求
- 后缀数组倍增算法模板详解
- 后缀数组 倍增算法模板
- 后缀数组 倍增算法详解
- 后缀数组 倍增算法 代码详解
- 后缀数组 倍增算法
- 后缀数组,倍增算法
- 后缀数组-倍增发(模板)
- 后缀数组 倍增法模板
- 倍增算法实现后缀数组
- 后缀数组之倍增算法
- 后缀数组倍增算法模版
- 后缀数组之倍增算法
- 后缀数组——罗穗骞倍增算法代码详解
- 后缀数组模板(倍增法)
- 后缀数组二倍增模板解析
- 倍增算法求解字符串的后缀数组
- 后缀数组,Manber & Mayer 倍增算法
- 后缀数组 (由倍增算法构造)
- Https系列之四:https的SSL证书在Android端基于okhttp,Retrofit的使用
- relativelayout等布局点击事件无效
- redisTemplate.keys(pattern)模糊查询找不到keys
- linux grep 正则表达式
- 【安全牛学习笔记】FUZZING
- 后缀数组倍增算法模板详解
- win7 远程桌面连接centos 6.5
- Netty5的服务端
- 这样用思维导图,月薪岂止翻两倍!
- java历史变迁
- Spring 使用 ajax
- 史上最全CentOS安装教程,图文结合
- Android Studio依赖aar
- Testing