查找不包含整个字符集的所有子字符串

时间:2014-01-14 14:42:46

标签: algorithm language-agnostic

这是在接受采访时向我询问的。

我给了一个字符串,其字符仅来自集合{a,b,c}。查找不包含集合中所有字符的所有子字符串。例如,仅包含a的子字符串,仅包含b,仅包含c或仅包含a,b或仅包含b,c或仅包含c,a。我通过生成所有子串并测试它们给了他天真的O(n ^ 2)解决方案。

面试官想要一个O(n)解决方案。

编辑:我的尝试是使用a,b,c的最后一个索引并从左到右运行一个指针,并且任何时候所有3个都被计算在内,更改子字符串的开头以排除最早的一个并再次开始计数。它似乎并不详尽

因此,例如,如果字符串是abbcabccaa, 让i成为遍历字符串的指针。让start成为子字符串的开头。

1)i = 0,start = 0

2)i = 1,start = 0,last_index(a)= 0 - > 1个子串 - 一个

3)i = 2,start = 0,last_index(a)= 0,last_index(b)= 1 - > 1 substring ab

4)i = 3,start = 0,last_index(a)= 0,last_index(b)= 2 - > 1 substring abb

5)i = 4,start = 1,last_index(b)= 2,last_index(c)= 3 - > 1个子串bbc(从子串中删除了一个)

6)i = 5,start = 3,last_index(c)= 3,last_index(a)= 4 - > 1个子串ca(从子串中删除b)

但这并非详尽无遗

2 个答案:

答案 0 :(得分:0)

为了获得比O(n)更好的东西,我们可能需要额外的假设(可能最长的子串具有此属性)。 考虑长度为n的aaaaaaaaaabbbbbbbbbb形式的字符串。至少有O(n ^ 2)个可能的子串,所以如果我们想要列出它们,我们需要O(n ^ 2)时间。

我想出了最长子串的线性解决方案

从由S分隔的所有子字符串中设置a,将所有子字符串分隔为b,最后将所有子字符串分隔为c。每个步骤都可以在O(n)中完成,因此我们有O(3n),因此O(n)。

示例:aaabcaaccbaa

在这种情况下,设置S包含:

  • a分隔的子字符串:bcccb
  • b分隔的子字符串:aaacaacc
  • c分隔的子字符串:aaabaabaa

set 是指在O(1)中添加和查找具有给定键的元素的数据结构。

答案 1 :(得分:0)

鉴于原始定义中的问题无法在O(N ^ 2)时间内解决,正如一些评论指出的那样,我建议用计算子串数的线性算法(它们的价值不一定是唯一的,但在原始字符串中的位置是唯一的。)

算法

  1. count = 0
  2. 对于{'a','b','c'}中的每个字符C扫描输入S并将其分解为不包括C的最长序列。对于每个这样的A部分,添加| A | *(| A | +1)/ 2来计算。此添加代表A中合法子字符串的数量。
  3. 现在我们有合法字符串的总数,仅包括{'a','b'},仅{'a','c'}和{b','c'}。问题是我们用一个重复的字符计算子字符串两次。为了解决这个问题,我们再次迭代S,这次为我们遇到的单个字符的每个最大序列A减去 | A | *(| A | +1)/ 2。
  4. 返回计数
  5. 示例

    S = 'AACB'

    使用'a'打破它只给'cb',所以count = 3.对于C ='b',我们有'aac',这使得count = 3 + 6 = 9.使用C ='c'我们得到'aa'和'b',所以count = 9 + 3 + 1 = 13.现在我们要做减法:'aa': - 3,'c': - 1,'b': - 1。所以我们 count = 8

    8个子串是:

    'a'
    'a' (the second char this time)
    'aa'
    'ac'
    'aac'
    'cb'
    'c'
    'b'