最有效的算法是计算包含给定字符的给定字符串的子字符串数。
例如对于abb b
子字符串:a,b,b,ab,bb,abb。 答案:包含b atlest的字符串一次= 5。
PS。我通过生成所有子字符串然后检查O(n ^ 2)解决了这个问题。只是想知道是否有更好的解决方案。
答案 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
。
a
位于索引4
处,因此包含a
的子字符串的数量是从abcda
到{{1} }。因此,我们添加aefgabb
= (4-0 + 1) + (10 - 4)
。这些将子字符串表示为11
,abcda
,bcda
,cda
,da
,a
,ae
,{{1} },aef
,aefg
和aefga
。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是不包含目标的字母的游程长度。