后缀数组代码详解
2015-09-24 10:50
363 查看
// // main.cpp // 后缀数组模板详解 // // Created by XD on 15/9/24. // Copyright © 2015年 XD. All rights reserved. // #include <iostream> using namespace std ; const int maxn = 10000 ; int s[maxn] ; int sa[maxn],t1[maxn] , t2[maxn] ,c[maxn] ; void getSa(int n,int m ) { int i , j ; int *x = t1 , *y = t2 ,*temp; for(int i = 0 ; i <=m ; i++) c[i] =0 ; for(int i = 0 ; i < n ; i++) c[x[i] = s[i]]++ ; for(i = 1 ; i <=m ; i++) c[i] += c[i-1] ; for(int i = n-1 ; i >-1 ; i -- ) sa[--c[x[i]]] = i ; //下面是最关键的一段代码 for(int k = 1 ; k <= n ; k*= 2 ) { int p =0 ; //先计数排序第二关键字,这里不需要重复计数排序的步骤,因为在上一次的排序过后,是第一关键字的顺序,可是根据倍增算法的特点,这一次的第二关键字的顺序与上一次的排序的第一关键字(注意有的位置后面是没有第二关键字的) //这是因为从 n - k到n-1的位置上第二关键字都是没有的。这是设为最小的,因为当一个字符串是另一个字符串的前缀时,后面的子符串是较大的。这里还有一个问题,有人说可能第一关键字都是不完整的,那为什么可以比较大小呢。因为我们在原字符串的末尾加了一个$,我们认为这个$符号是最小的,又用因为后缀的长度是不同的,所以在仅有的长度下就可以比较出大小,因此即使有的关键字没达到k的长度,但是任然是可行的。 for(i = n - k ; i < n ; i ++ ) y[p++] = i ; //这里是对具有第二关键字的那部分排序,当然不能忽略不具有第一关键字的那部分,因此才有sa[i]>=k. for(i = 0 ; i < n ; i ++) if(sa[i]>=k) y[p++] = sa[i] - k ; //对第一关键字排序 for(i = 0 ; i <=m; i++) c[i] = 0 ; //这里是x[y[i]]的原因是对第二关键字排序后,需按照其结果的对第一关键字排序,而y[i]存的是第一关键字的位置 for(i = 0 ; i < n ;i++) c[x[y[i]]]++ ; for(i = 1 ;i<=m;i++) c[i] += c[i-1] ; for(i = n - 1; i > -1;i--) sa[--c[x[y[i]]]] = y[i] ; //下面要更新x数组 temp = x ; x = y ; y = temp ; x[sa[0]] = 1 ; p=1; for(i = 1 ; i < n ;i++) { //根据排序确定下一次的x数组的值 x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i] + k]==y[sa[i-1] + k ])? p : ++p ; } if(p >= n){ break ; } m = p ; } } int main(int argc, const char * argv[]) { int n ; while (scanf("%d" , &n),n) { for (int i= 0 ; i < n ; i++) { scanf("%d" , &s[i]) ; s[i]++ ; } s =1 ; getSa(n+1 , 100) ; for (int i = 0; i <= n; i++) { printf("%d ",sa[i]) ; } } return 0; }
相关文章推荐
- java数组获取最值
- 开发中遇到libc++abi.dylib: terminate_handler unexpectedly threw an exception错误
- java生成pdf报表
- 【4】Windows客户端C/C++编程规范“建议”——表达式和运算
- Spring - Spring Data REST - Prevent The Methods in Event Handlers Be Triggered Twice
- Java中产生随机数的方法
- [ASP.NET]分析MVC5源码,并实现一个ASP.MVC
- 【3】Windows客户端C/C++编程规范“建议”——函数调用
- C函数指针妙用,用c语言写一个简易类
- 【2】Windows客户端C/C++编程规范“建议”——指针
- PHP的四种运行方式
- php 设置时区
- 【转】java byte转long、double、float、int、short,或者long、double、float、int、short转byte
- java学习笔记IO输入与输出——IO流概述及字节流(2)
- java 适配器模式
- 深入详解Struts2——Struts2初识
- Eclipse:引用一个项目作为类库(图文教程)
- 【转】java读写二进制文件的解决方法
- 【转】JAVA 读写二进制文件
- java学习3-二分法查找法