Suffix Array 后缀数组
2015-08-25 00:19
274 查看
后缀数组
顾名思义,SuffixArray(以下有时简称SA) 和字符串的后缀有关。后缀:字符串中某个位置一直到结尾的子串。(SA中讨论包括了原串和空串),所以共有len+1个后缀。
后缀数组: 字符串的所有后缀组成的按字典序从小到大排好的数组。由于SA中记录的都是字符串的后缀,所以SA只需要记录其表示的后缀的起始位置。
由于比较字典序是O(n)的,所以暴力算法的复杂度将是O(n^2logn)。通过一些算法可以降到线性复杂度。这里先介绍一种简单的O(nlognlogn)的算法。
该算法的思想是通过倍增法降低了比较字典序的大小的复杂度O(n)到O(logn)。其求解时不先算后缀,而是先算长度为1的子串的字典序大小排列,然后得到一个rank数组,即该子串在所有子串中排位的值。字典序越小,rank值越小。
rank[k][i] 表示起始位置为i的长度为k的子串在所有长度为k的子串中的字典序大小。
这时我们要比较长度为2k的子串的大小的话,其第i个位置的长度为2k的子串的大小可以通过比较rank[k][i]和rank[k][i+k]来实现。
SA中的sa[i]表示字典序位i的后缀串的起始位置。
const int MAXN = 100000 + 5; int _k, _len; int _rank[MAXN]; int _tmp[MAXN]; int _sa[MAXN];// 后缀数组。 bool _cmp(int i, int j) { if (_rank[i] == _rank[j]) { int _ri = (i+_k <= _len) ? _rank[i+_k] : -1; int _rj = (j+_k <= _len) ? _rank[j+_k] : -1; return _ri < _rj; } else { return _rank[i] < _rank[j]; } } void Suffix_sa(string s, int* sa) { _len = s.size(); for (int i=0; i<_len; i++) { sa[i] = i; _rank[i] = s[i]; } sa[_len] = _len; _rank[_len] = -1; for ( _k=1; _k<=_len; _k<<=1) { sort(sa, sa+_len+1, _cmp); _tmp[sa[0]] = 0; for (int i=1; i<=_len; i++) { _tmp[sa[i]] = _tmp[sa[i-1]]; if (_cmp(sa[i-1], sa[i])) { _tmp[sa[i]]++; } } copy(_tmp, _tmp+_len+1, _rank); } }
相关文章推荐
- ThinkPHP使用入门实例
- 【Material Design】主题与布局
- 窗口的基本手势事件处理
- tcpclient
- 深入理解Ajax
- 设计模式--观察者模式
- 在x86为arm 编译 httpd 2.2.31
- [Java Concurrency in Practice]第六章 任务执行
- mysql CHAR_LENGTH()与LENGTH()
- STM32+TFT彩屏实现汉字字库显示
- MongoDB(1)--简介以及安装
- [POJ2001]Shortest Prefixes
- iOS 另外一个使用类的代码,四则运算,很简单,熟悉以下
- POJ3181--Dollar Dayz
- phpstorm通过ftp远程开发服务器上的项目
- JavaScript设置自适应居中
- android ble 4.0实现自动配对
- 链表
- 用命令行(CMD)中启动和关闭ORACLE服务
- UVA 11427 Expect the Expected (概率dp+推公式求期望 详解)