【问题标题】:String manipulation: calculate the "similarity of a string with its suffixes"字符串操作:计算“字符串与其后缀的相似度”
【发布时间】:2018-11-26 07:45:11
【问题描述】:

对于两个字符串 A 和 B,我们将字符串的相似度定义为两个字符串共有的最长前缀的长度。例如字符串“abc”和“abd”的相似度为2,而字符串“aaa”和“aaab”的相似度为3。

问题是给出一个算法来计算字符串 S 与其每个后缀的相似性总和。例如,让字符串为:ababaa。那么,字符串的后缀是ababaababaaabaabaaaaa。这些字符串中的每一个与字符串ababaa 的相似性分别为6,0,3,0,1,1。因此答案是6 + 0 + 3 + 0 + 1 + 1 = 11

【问题讨论】:

  • 那么你有没有尝试解决它?你在哪里卡住了?您需要什么样的帮助?
  • Ukkonen算法的实现在O(n)中构建前缀树gist.github.com/3355993
  • Ukkonen 的算法用于构建 suffix 树,当然这正是本文的目的。后缀树与后缀数组并不完全相同,尽管它们显然是相关的。

标签: string algorithm


【解决方案1】:

你想考虑suffix arrays。单词的后缀数组是按字典顺序排序的后缀索引数组。在链接的维基百科文章中,算法在计算后缀数组时计算 LCP(最长公共前缀)。您可以使用与suffix trees 的相似性在O(n) 中计算此值,如this paper 所示。

示例:您的字符串是ababaa,因此后缀数组如下所示:

5 | a
4 | aa
2 | abaa
0 | ababaa
3 | baa
1 | babaa

其中左边的数字是后缀开始的索引。现在计算前缀很容易,因为所有内容都按字典顺序存储。

附带说明,这与longest common substring 问题密切相关。要为下一次面试练习,请考虑有效解决问题的方法。

【讨论】:

  • :非常感谢!我明白你在说什么,但我对后缀树一点也不熟悉,鉴于时间有限,我想问你,如果你能看看 Knuth morris prat algotihm 会有所帮助
  • @PengOne :我尝试构建后缀树,但左侧的数量,即 LCP 在 str[i - 1] 和 str[i] 之间,他们正在寻找的是“ababaa”和"a" , "ababa" 和 "aa" , "ababaa" 和 "abaa" 等等..我的解决方案失败了,因为我在这里进行线性比较,还有更多线索。
  • @PengOne 你能解释一下如何使用后缀数组解决这个特殊问题吗?或者,与手动将每个后缀与原始字符串进行比较相比,字典顺序对解决方案有什么好处。
  • @PengOne 制作后缀数组甚至LCP后怎么办?
【解决方案2】:

首先阅读有关z-algorithm 的链接。 基于python实现的链接算法的O(n)解决方案:

def z_func(s):
    z = [0]*len(s)
    l, r = 0, 0
    for i in range(1,len(s)):
        if i<=r:
            z[i] = min(r-i+1, z[i-l])
        while (i + z[i] < len(s) and s[z[i]] == s[i + z[i]]):
            z[i] += 1
        if z[i]+i-1 > r:
            l, r = i, z[i]+i-1
    return sum(z)+len(s)

【讨论】:

    猜你喜欢
    • 2013-02-24
    • 2011-04-04
    • 2018-03-08
    • 2017-02-28
    • 1970-01-01
    • 2011-12-10
    • 2011-08-17
    • 2017-04-26
    • 2015-09-10
    相关资源
    最近更新 更多