后缀数组模板
2016-03-27 00:01
281 查看
将罗穗骞论文《后缀数组--处理字符串的有力工具》中的实现修改后的版本。
void SA(int *s, int *sa, int *sa2, int *rk, int *cnt, int *hgt, int n, int m){ //counting sort for(int i=0; i<m; i++) cnt[i]=0; for(int i=0; i<n; i++) cnt[rk[i]=s[i]]++; for(int i=1; i<m; i++) cnt[i]+=cnt[i-1]; for(int i=n-1; i>=0; i--) sa[--cnt[rk[i]]]=i; //stable sort for(int len=1; len<n; len*=2){ //stp.1 fill sa2[] int p=0; for(int i=n-len; i<n; i++) sa2[p++]=i; for(int i=0; i<n; i++) if(sa[i]>=len) sa2[p++]=sa[i]-len; //stp.2 fill sa[], countig sort for(int i=0; i<m; i++) cnt[i]=0; for(int i=0; i<n; i++) cnt[rk[i]]++; for(int i=1; i<m; i++) cnt[i]+=cnt[i-1]; for(int i=n-1; i>=0; i--) sa[--cnt[rk[sa2[i]]]]=sa2[i]; //stp.1 and stp.2 together is radix sort //fill rk[] swap(rk, sa2); rk[sa[0]]=0; for(int i=1; i<n; i++) rk[sa[i]]=rk[sa[i-1]]+!same(sa2, sa[i-1], sa[i], len); m=rk[sa[n-1]]+1; if(m==n) break; } //CALCULATE hgt[] for(int i=0, j, lcp=0; i<n-1; i++){ lcp?--lcp:0; // rk[i]>0 j=sa[rk[i]-1]; for(; s[j+lcp]==s[i+lcp]; lcp++); hgt[rk[i]]=lcp; } }
注意:
1.s[ ]数组的末尾必须补一个“0”,这里“0”的含义是:比s[ ]中其他元素都小的一个值。因而函数
void SA(int *s, int *sa, int *sa2, int *rk, int *cnt, int *hgt, int n, int m)
的参数 n 是 s[ ] 的实际长度再加 1 .
2.由于s[ ]的末尾补了零,必然有:
sa[0]=n (0-indexed)
rk
=0
rk
=0,意味着rk[0...n-1] > 0
所以求hight数组时,循环才可写成:
for(int i=0, j, lcp=0; i<n-1; i++){ lcp?--lcp:0; // rk[i]>0 j=sa[rk[i]-1]; for(; s[j+lcp]==s[i+lcp]; lcp++); hgt[rk[i]]=lcp; }
因为s[rk[i]-1]不会越界。补"0"以后,hgt[1...n]都变得 well-defined 了。
3. 在函数SA()中,参数rk和sa作为两个指针使用,由于有
swap(rk, sa2);
这一句,在 SA() 外部,我们不知道 sa2[] 和 rk[] 这两个数组里装的分别是什么,这时如果要用 rk[] 数组必须从sa[] 数组重新构造一遍:
for(int i=0; i<=n; i++) rk[sa[i]]=i;
注意:
- 这里的 n 指的是数组的实际长度, 而非末尾补 "0" 后的长度 (后者是作为SA()的参数的 n), 下同
- 因此, for-head 里的判断 i<=n 不能写成 i<n ,因为 sa[ ] 数组是按照补 “0” 后的 s[ ] 数组算得的,必然有 sa[0]=n , 若写成 < 就漏掉 rk[sa
]了.
相关文章推荐
- ASP.NET MVC Layout如何嵌套
- ASP.NET中JQuery+AJAX调用后台
- 解决ASP.NET中"/"应用程序中的服务器错误的方法
- PHP连接数据库实现注册页面的增删改查操作
- 计算机网络协议层
- 基于javascript实现九九乘法表
- js事件处理程序跨浏览器解决方案
- 详解javascript跨浏览器事件处理程序
- Bootstrap每天必学之级联下拉菜单
- JavaScript html5 canvas绘制时钟效果(二)
- SQL(MSSQLSERVER)服务启动错误代码3414的解决方法
- SQL附加数据库失败问题的解决方法
- SQL Server评估期已过问题的解决方法
- 程序员人傻钱多死的早都便宜了别人?say no
- 罗振宇:网红是长不了的,我们要一次性的把未来收割掉,落袋为安
- Google首席科学家谈Google是怎么做深度学习的
- 奶茶一年半解决人生大事:7月毕业8月扯证3月生子
- 竞品分析三步走,你了解么?
- C++中的explicit关键字
- 雷军回应飞猪理论:任何人成功都需要一万小时的苦练