倍增算法求解字符串的后缀数组

    今天完成了使用倍增算法求解字符串的后缀数组的程序。倍增算法的主要思想是:

对每个字符开始的长度为2k的子字符串进行排序,求出排名,即Rank值。k0开始,每次加1,当2k大于n以后,每个字符开始的长度为2k的子字符串便相当于所有的后缀。并且这些子字符串都一定已经比较出大小,即Rank值中没有相同的值,那么此时的Rank值就是最后的结果。每一次排序都利用上次长度为2k-1的字符串的Rank值,那么长度为2k的字符串就可以用两个长度为2k-1的字符串的排名作为关键字表示,然后进行基数排序,便得出了长度为2k的字符串的Rank值。

因为我们知道有Rank[i] = j 等价于 SA[j] = i;故可以利用这一点求出相应字符串的后缀数组。其时间复杂度是O(nlogn)。

 

 

 #include #include #include using namespace std; void select(int *arrays,string str) { for(unsigned i = 0; i < str.length();i++) { switch(str.at(i)) { case '$': arrays[i] = 1; break; case 'b': arrays[i] = 2; break; case 'e': arrays[i] = 3; break; case 'n': arrays[i] = 4; break; case 'o': arrays[i] = 5; break; case 'r': arrays[i] = 6; break; case 't': arrays[i] = 7; break; default: exit(0); } } } const int MAX = 20; typedef struct radixArray{ int x; int y; int pos; }Radix_Array; Radix_Array RadixArr[MAX]; typedef struct bnode{ Radix_Array data; struct bnode *next; }node; typedef struct Bucket{ int no; node *next; }bucket; bucket bcket[14]; void RadixSort(Radix_Array RadixArr[],int *Rank,int n) { for(int i = 0; i < 14;i++) { bcket[i].no = 0; bcket[i].next = NULL; } for(int i = 0; i < n;i++) { node *tmp = new node; tmp->data.x = RadixArr[i].x; tmp->data.y = RadixArr[i].y; tmp->data.pos = RadixArr[i].pos; tmp->next = NULL; if(bcket[tmp->data.x - 1].next == NULL) { bcket[tmp->data.x - 1].next = tmp; } else { node *tm = bcket[tmp->data.x - 1].next; node *per = new node; while(tm->next != NULL && tm->data.y <= tmp->data.y) { per = tm; tm = tm->next; } if(tm->next == NULL) { //插到桶链表的第一个节点 if(tm == bcket[tmp->data.x - 1].next && tm->data.y > tmp->data.y) { bcket[tmp->data.x - 1].next = tmp; tmp->next = tm; } //插入到桶链表的倒数第一个节点之前 else if (tm->data.y > tmp->data.y) { per->next = tmp; tmp->next = tm; } else //插入到桶链表的最后一个节点 tm->next = tmp; } else //插入到桶的中间某个节点 { per->next = tmp; tmp->next = tm; } } } for(int j = 0; j < 14; j++) { node *tm = bcket[j].next; while(tm != NULL) { cout<<"("<data.x<<","<data.y<<","<data.pos<<") "; tm = tm->next; } } cout<data.pos] = v; node *pre = tm; if(tm->next != NULL) { if(tm->next->data.y != tm->data.y) { v++; Rank[tm->next->data.pos] =v; } else Rank[tm->next->data.pos] = v; } tm = tm->next; } v++; } for(int i = 0; i < n; i++) cout<

该程序实现了后缀数组的O(nlogn)时间复杂度的求解。唯一的问题就是空间复杂度比paper中提到的要高。

你可能感兴趣的:(后缀数组相关算法实现,算法,arrays,null,struct,string,system)