首先说明 :后缀数组的构建在网上有多种方法:朴素的n*n*logn,还有倍增n*logn的,还有3*n的DC3算法,当然还有DC算法。这个算法学习自林厚丛老师的《高级数据结构》,代码较长,而且常数也比较大,但是是我这种笨人可以理解的。如有人想学短而快的可以学习《罗穗骞 后缀数组 ---处理字符串的有力工具》。顺便说一下,罗大神的算法书写的的确很短小也漂亮,可惜我看不懂。
说一下学习的心路历程吧!最开始想学后缀树,道理看明的了,可是一看代码实在是太长了(可能是我找的模版不对吧)。后来看到后缀数组的功能也不错,可以实现后缀树的很多功能,于是转向后缀数组。于是向林大神学习,可是在他漂亮的代码映照下的是我愚笨的脑袋,最后是林厚丛老师救了我。感谢林老师!!!
学习前的准备:
1、后缀数组的各种基本概念
后缀:字符串中从第i个开始到它的最后一个。如字符串abcde。则bcde、cde、de、e都是他的后缀,当然他本身也是自己的后缀。
后缀数组:有两种sa数组和rank数组。
sa[i]表示把字符串的所有后缀排序后排第i的是以第几个字母开头的后缀。
rank[i]表示以第i个字母开头的后缀在后缀的排序中排第几。
2、计数排序和基数排序(可以百度一下)
计数排序也就是桶排,时间复杂度O(n)
1 #include <iostream> 2 using namespace std; 3 const int MAXN = 100000; 4 const int k = 1000; // range 5 int a[MAXN], c[MAXN], ranked[MAXN]; 6 7 int main() { 8 int n; 9 cin >> n; 10 for (int i = 0; i < n; ++i) { 11 cin >> a[i]; 12 ++c[a[i]]; 13 } 14 for (int i = 1; i < k; ++i) 15 c[i] += c[i-1]; 16 for (int i = n-1; i >= 0; --i) 17 ranked[--c[a[i]]] = a[i];//如果是i表达的是原数标号,a[i]就是排序后的正确序列 18 for (int i = 0; i < n; ++i) 19 cout << ranked[i] << endl; 20 return 0; 21 }