是否可以在O(n)中计算字符串中不同子串的数量?

时间:2016-01-19 17:00:26

标签: string algorithm substring time-complexity suffix-tree

给定长度为.的字符串s,是否可以计算O(n)中n中不同子串的数量?

示例

输入:s

输出:abb5

我做了一些研究,但我似乎无法找到一种能够以如此有效的方式解决这个问题的算法。我知道O(n ^ 2)方法是可行的,但是有更高效的算法吗?

我不需要获得每个子串,只需要获得不同的子串(如果它有所不同)。

2 个答案:

答案 0 :(得分:10)

您可以使用Ukkonen算法在线性时间内构建后缀树:

https://en.wikipedia.org/wiki/Ukkonen%27s_algorithm

s的子串数是trie中字符串的前缀数,您只需在线性时间内计算。它只是所有节点中的总字符数。

例如,您的示例生成一个后缀树,如:

            /\                
           b  a
           |  b
           b  b

树中有5个字符,所以有5个子串。每个唯一字符串是从根后以不同字母结尾的路径:abb,ab,a,bb,b。所以字符串的数量是树中字母的数量。

更确切地说:

  • 每个子字符串都是字符串后缀的前缀;
  • 所有后缀都在trie中;
  • 因此,通过trie的子串和路径之间存在1-1对应关系(通过trie的定义);和
  • 树中的字母与非空路径之间存在1-1对应关系,因为:
    • 每个不同的非空路径在其最后一个字母后面的不同位置结束;和
    • 每个字母后面的位置路径是唯一的

注意那些想知道如何在O(N)时间内构建包含O(N ^ 2)个字符的树的人:

表示后缀树的技巧。您只需将指针存储到orignal字符串中,而不是将实际字符串存储在树的节点中,因此包含" abb"没有" abb",每个节点有(0,3) - 2个整数,无论​​每个节点中的字符串有多长,后缀树有O(N)个节点

答案 1 :(得分:2)

构造LCP array并从子串数(n(n + 1)/ 2)中减去其总和。