后缀数组构建–倍增算法java实现
当把倍增算法的流程图画出来之后,就可以理解算法的流程。按照这个流程实现,我开始采用treemap来进行排序,10^5的长度的字符串,耗时10秒左右。今天按照某Acmer的代码,实现了java版的。性能提升接近100倍。Acmer写的代码,一般效率很高,但是可读行非常差,阅读代码的人经常绕在里面出不来了。下面,我详细分析一下java版的实现,希望自己加深理解,也能够帮助同学,欢迎指教。
代码解释:整体思想,参考前面的博客《后缀数组构建-倍增算法分析》。函数接收三个参数:
子串长度为1的时候,rank数组为[1,1,2,1,1,1,1,2],suffix数组为[0,1,3,,4,5,6,2,7],接着处理子串长度为2的情况:aa,ab,ba,aa,aa,aa,ab,b$($表示空)。suffix数组为[7,0,2,3,4,5,1,6]。通过观察,我们发现,7=8-1,0=1-1,2=3-1等等。就找到了规律,再试几组,会得到,后面的减1,就是减j。27-35行是采用计数排序的第二次基数排序,求得后缀数组。36、37行是由后缀数组得到rank数组,这里最需要注意的是:有的子串是相同的,需要判断,如果相同的,rank值也是相同的。
后面的代码比较好理解,不多解释。阅读Acmer的代码的心得:代码效率确实高,但是可读性奇差无比。这个在实际项目中,需要注意,要兼顾效率和代码的可读性。
这几天学习算法的一个重要的心得:多在纸上画画过程。
【引用】

- 待排序的数组:这里有两点注意,数组元素类型是整形的,要先将字符转化为整形,方法采用转ASCII码的方法即可;还有就是,数组的长度是实际待排元素的两倍,也就是2*n,为什么后面会讲到。
- 待排元素的长度,就是待排数组的前n个元素,才是真的参与排序的。
- 计数排序数组的大小,为待排数组中元素最大的+1

IOI国家集训队2009年论文《后缀数组——处理字符串的有工具》(罗穗骞)。