给定字符串中包含特定字符的子字符串数

时间:2019-04-11 14:14:45

标签: algorithm data-structures

最有效的算法是计算包含给定字符的给定字符串的子字符串数。

例如对于abb b

子字符串:a,b,b,ab,bb,abb。 答案:包含b atlest的字符串一次= 5。

PS。我通过生成所有子字符串然后检查O(n ^ 2)解决了这个问题。只是想知道是否有更好的解决方案。

4 个答案:

答案 0 :(得分:2)

让您需要找到字符X的子字符串。

从左到右扫描字符串,保留最后一个X:lastX的位置,起始值为-1

当您在位置i处遇到X时,请添加i+1作为结果并更新lastX
(这是在当前位置结束的子字符串的数量,它们都包含X)

遇到另一个字符时,将lastX + 1添加到结果中
(这也是在当前位置结束并包含X的子字符串的数量),
因为子串最右边的开始是最后一个X的位置

算法是线性的。
示例:

a X a a X a
            good substrings                            overall     
idx  char   ending at idx             lastX   count    count
 0    a      -                        -1       0        0  
 1    X     aX X                       1       2        2 
 2    a     aXa Xa                     1       2        4
 3    a     aXaa Xaa                   1       2        6 
 4    X     aXaaX XaaX aaX aX X        4       5        11 
 5    a     aXaaXa XaaXa aaXa aXa Xa   4       5        16 

Python代码:

def subcnt(s, c):
    last = -1
    cnt = 0
    for i in range(len(s)):
        if s[i] == c:
            last = i
        cnt += last + 1
    return cnt

print(subcnt('abcdba', 'b'))

答案 1 :(得分:0)

让我们将字符串视为abcdaefgabb,并将给定字符视为a

  • 通过char遍历字符串char。
  • 如果某个字符与给定字符匹配,则假设a位于索引4处,因此包含a的子字符串的数量是从abcda到{{1} }。因此,我们添加aefgabb = (4-0 + 1) + (10 - 4)。这些将子字符串表示为11abcdabcdacdadaaae,{{1} },aefaefgaefga
  • 这适用于在任何地方找到aefgab的情况,就像在索引aefgabb和索引a上找到它一样。
  • 最终答案是上述数学运算的总和

更新:您将必须在最后一次发生的0与当前发生的8之间保持2个指针,以避免计算重复的,以相同索引结尾的子字符串。 / p>

答案 2 :(得分:0)

您可以将其转过来并扫描字符串以查找字母的出现。每次在某个位置i上发现一个事件时,您就会知道它是按定义包含在所有包含它的子字符串中的(即,所有在i之前或之后{ {1}}),因此您只需要存储索引对即可定义子字符串,而无需显式存储子字符串。

话虽如此,您仍然需要采用这种方法来处理 O(n²),因为尽管您不介意如示例所示的重复子字符串,但是您不想计数相同的子字符串两次,因此您仍然必须确保不要两次选择同一对索引。

答案 3 :(得分:0)

认为子字符串是从字符串中字母之间的间隙中选择两个元素,并包括它们之间的所有内容(字符串的最末端存在间隙)。

对于长度为n的字符串,有choice(n + 1,2)个子字符串。

其中,对于每k个不包含目标的字符,都有select(k + 1,2)个子字符串,这些子字符串仅包含该子字符串中的字母。主字符串的所有其他子字符串必须包含目标。

答案:select(n + 1,2)-sum(choose(k_i + 1,2)),其中k_i是不包含目标的字母的游程长度。