笨办法学 Python · 续 练习 22:后缀数组
来源:互联网 发布:表示喜欢的网络用语 编辑:程序博客网 时间:2024/06/14 07:31
练习 22:后缀数组
原文:Exercise 22: Suffix Arrays
译者:飞龙
协议:CC BY-NC-SA 4.0
自豪地采用谷歌翻译
我想告诉你一个关于后缀数组的故事。在一段时间里,我正在西雅图的一家公司面试,当时好奇的是如何最有效地创建一个用于可执行二进制文件的diff
。我的研究给我带来了后缀数组和后缀树。后缀数组只是,将字符串的所有后缀排序,储存到有序列表中。后缀树是类似的,但是比列表更像BSTree
。这些算法相当简单,一旦你进行了排序操作,它们就具有很快的性能。他们解决的问题是,找到两个字符串之间最长的公共子串(或者在这种情况下是字节列表)。
你可以在 Python 中轻易创建一个后缀数组:
>>> magic = "abracadabra">>> magic_sa = []>>> for i in range(0, len(magic)):... magic_sa.append(magic[i:])...>>> magic_sa['abracadabra', 'bracadabra', 'racadabra', 'acadabra', 'cadabra', 'adabra', 'dabra', 'abra', 'bra', 'ra', 'a']>>> magic_sa = sorted(magic_sa)>>> magic_sa['a', 'abra', 'abracadabra', 'acadabra', 'adabra', 'bra', 'bracadabra', 'cadabra', 'dabra', 'ra', 'racadabra']>>>
正如你所看到的,我只是按顺序取下字符串的后缀,然后对列表进行排序。但是,这对我有什么用呢?一旦我有了这个列表,那么我可以通过这个列表的二分搜索,来找到我想要的任何后缀。这个例子很简陋,但是在实际的代码中,你可以很快地做到它,你可以跟踪所有的原始索引,所以你可以引用后缀的原始位置。它与其他搜索算法相比非常快,对于 DNA 分析等事情非常有用。
回到西雅图的面试。我在这个寒冷的房间被 C++ 程序员面试,为了一份 Java 工作。你可以断定,这不是一个非常有趣的面试,我绝对不会认为我会得到这份工作。在多年的时间中,我没有写过任何 C++,而且这个工作是针对 Java 的,当时我是一个 Java 专家。下一个面试官来了,他问我:“如何在字符串中寻找子串?”
太棒了!我在空闲时间里一直在研究这个问题。我当然知道!我跳起来走到白板,向那个家伙解释如何制作一个后缀树,它如何提高搜索性能,修改后的堆排序如何更快,后缀树的工作原理,为什么它比三叉搜索树更好,以及如何在 C 中实现。我想,如果我可以展示如何在 C 中写出来,那么这将证明,我不只是一个核心能力的 Java 码工。
那个家伙很震惊,就像我在采访室里打开一袋新鲜的榴莲一样。他看着董事会,并且有些结巴,“呃,我是在寻找一些有关 Boyer-Moore 搜索算法的东西吗?你知道吗?我愁眉苦脸地说:“是啊,就像 10 年前一样。” 他摇摇头,拿着他的东西,起身说:“好吧,我会让大家知道我的想法。”
几分钟后,下一个面试官来了。他抬头看着白板,笑了起来并嘲笑我,然后问我另一个 C++ 模板元编程问题,我无法回答。我没有得到这份工作。
挑战练习
在这个练习中,你将会使用我的 Python 小会话并创建自己的后缀数组搜索类。该类将使用一个字符串,将其拆成后缀列表,然后对其进行以下操作:
find_shortest
找到以它开始的最短子串。在上面的例子中,如果我搜索
abra
,那么它应该返回abra
,而不是abracadabra
。
find_longest
找到以它开始的最长子串。如果我搜索
abra
,你返回abracadabra
。
find_all
查找以它开始的所有子串。这意味着
abra
返回abra
和abracadabra
。
你将需要对此进行良好的自动测试,并进行一些性能测量。我们将在以后的练习中使用它们。完成之后,你需要进行研究性学习来完成这个练习。
研究性学习
- 一旦你的测试正常工作,使用你的
BSTree
重写它,进行后缀排序和搜索。你还可以使用每个BSTreeNode
的value
,来跟踪原始字符串中存在该子串的位置。然后,你可以保留原始字符串。 BStree
如何为不同搜索操作更改你的代码?是否使其更简单或更难?
深入学习
彻底研究后缀数组及其应用。它们非常有用,但不是被大多数程序员熟知。
- 笨办法学 Python · 续 练习 22:后缀数组
- 笨办法学 Python · 续 练习 5:`cat`
- 笨办法学 Python · 续 练习 6:`find`
- 笨办法学 Python · 续 练习 8:`cut`
- 笨办法学 Python · 续 练习 7:`grep`
- 笨办法学 Python · 续 练习 9:`sed`
- 笨办法学 Python · 续 练习 10:`sort`
- 笨办法学 Python · 续 练习 11:`uniq`
- 笨办法学 Python · 续 练习 12:复习
- 笨办法学 Python · 续 练习 3:质量
- 笨办法学 Python · 续 练习 2:创造力
- 笨办法学 Python · 续 练习 13:单链表
- 笨办法学 Python · 续 练习 14:双链表
- 笨办法学 Python · 续 练习 17:字典
- 笨办法学 Python · 续 练习 18:性能测量
- 笨办法学 Python · 续 练习 0:起步
- 笨办法学 Python · 续 练习 19:改善性能
- 笨办法学 Python · 续 练习 21:二分搜索
- 二级列表SimpleExpandableListAdapter ,ExpandableListAdapter
- go语言开发必备
- PHP对接微信公众平台消息接口开发流程详解及实例(一)
- JAVA枚举(高级)
- android service的使用与理解
- 笨办法学 Python · 续 练习 22:后缀数组
- 暑假集训日记--8.9--搜索、图论专题总结
- The fish and bird-另类关系
- 图的基本存储的基本方式二
- MySQL语句大全
- Python模块之codecs
- linux系统调用过程解析(基于ARM处理器)
- 关于回滚段导致的ORA-01555错误
- 【C++】C++起步遇到的问题