Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
TinySTL
提交
2a6f77c0
T
TinySTL
项目概览
OpenDocCN
/
TinySTL
通知
4
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TinySTL
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
2a6f77c0
编写于
12月 30, 2014
作者:
邹
邹晓航
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加注释
上级
7784f65e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
18 addition
and
4 deletion
+18
-4
TinySTL/SuffixArray.h
TinySTL/SuffixArray.h
+18
-4
未找到文件。
TinySTL/SuffixArray.h
浏览文件 @
2a6f77c0
...
...
@@ -5,7 +5,7 @@
#include <memory>
namespace
TinySTL
{
class
suffix_array
{
private:
//typedef std::unique_ptr<std::vector<int>> vecPtr;
...
...
@@ -15,27 +15,41 @@ namespace TinySTL{
template
<
class
InputIterator
>
//arr - 源数组
//len - 源数组长度
//max_len - max_len代表字符串中字符的取值范围,是基数排序的一个参数,
//max_len - max_len代表字符串
arr
中字符的取值范围,是基数排序的一个参数,
// 如果原序列都是字母可以直接取128,如果原序列本身都是整数的话,则m可以取比最大的整数大1的值。
suffix_array
(
InputIterator
arr
,
int
len
,
in
t
max_len
=
128
){
suffix_array
(
InputIterator
arr
,
size_t
len
,
size_
t
max_len
=
128
){
//采用了罗穗骞论文中实现的倍增算法
//算法时间复杂度 = O(nlg(n))
_array
.
resize
(
len
);
int
wa
[
1024
],
wb
[
1024
],
wv
[
1024
],
ws
[
1024
];
int
i
,
j
,
p
,
*
x
=
wa
,
*
y
=
wb
,
*
t
;
//以下四行代码是把各个字符(也即长度为1的字符串)进行基数排序
for
(
i
=
0
;
i
<
max_len
;
i
++
)
ws
[
i
]
=
0
;
//x[]里面本意是保存各个后缀的rank值的,但是这里并没有去存储rank值,因为后续只是涉及x[]的比较工作,因而这一步可以不用存储真实的rank值,能够反映相对的大小即可。
for
(
i
=
0
;
i
<
len
;
i
++
)
ws
[
x
[
i
]
=
arr
[
i
]]
++
;
for
(
i
=
1
;
i
<
max_len
;
i
++
)
ws
[
i
]
+=
ws
[
i
-
1
];
//i之所以从len-1开始循环,是为了保证在当字符串中有相等的字符串时,默认靠前的字符串更小一些。
for
(
i
=
len
-
1
;
i
>=
0
;
i
--
)
_array
[
--
ws
[
x
[
i
]]]
=
i
;
//下面这层循环中p代表rank值不用的字符串的数量,如果p达到len,那么各个字符串的大小关系就已经明了了。
//j代表当前待合并的字符串的长度,每次将两个长度为j的字符串合并成一个长度为2*j的字符串,当然如果包含字符串末尾具体则数值应另当别论,但思想是一样的。
//max_len同样代表基数排序的元素的取值范围
for
(
j
=
1
,
p
=
1
;
p
<
len
;
j
*=
2
,
max_len
=
p
)
{
//以下两行代码实现了对第二关键字的排序
for
(
p
=
0
,
i
=
len
-
j
;
i
<
len
;
i
++
)
y
[
p
++
]
=
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
_array
[
i
]
>=
j
)
y
[
p
++
]
=
_array
[
i
]
-
j
;
//第二关键字基数排序完成后,y[]里存放的是按第二关键字排序的字符串下标
//这里相当于提取出每个字符串的第一关键字(前面说过了x[]是保存rank值的,也就是字符串的第一关键字),放到wv[]里面是方便后面的使用
//以下四行代码是按第一关键字进行的基数排序
for
(
i
=
0
;
i
<
len
;
i
++
)
wv
[
i
]
=
x
[
y
[
i
]];
for
(
i
=
0
;
i
<
max_len
;
i
++
)
ws
[
i
]
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
ws
[
wv
[
i
]]
++
;
for
(
i
=
1
;
i
<
max_len
;
i
++
)
ws
[
i
]
+=
ws
[
i
-
1
];
for
(
i
=
len
-
1
;
i
>=
0
;
i
--
)
_array
[
--
ws
[
wv
[
i
]]]
=
y
[
i
];
//下面两行就是计算合并之后的rank值了,而合并之后的rank值应该存在x[]里面,但我们计算的时候又必须用到上一层的rank值,也就是现在x[]里面放的东西,如果我既要从x[]里面拿,又要向x[]里面放,怎么办?
//当然是先把x[]的东西放到另外一个数组里面,省得乱了。这里就是用交换指针的方式,高效实现了将x[]的东西“复制”到了y[]中。
for
(
t
=
x
,
x
=
y
,
y
=
t
,
p
=
1
,
x
[
_array
[
0
]]
=
0
,
i
=
1
;
i
<
len
;
i
++
)
x
[
_array
[
i
]]
=
cmp
(
y
,
_array
[
i
-
1
],
_array
[
i
],
j
)
?
p
-
1
:
p
++
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录