Python 如何有效地计算字符串特定范围内给定字符的出现次数?

Python 如何有效地计算字符串特定范围内给定字符的出现次数?,python,arrays,string,algorithm,Python,Arrays,String,Algorithm,给定未排序的字符串,例如“googol”。我想找出[1,3]范围内字符“o”的出现次数。因此,在本例中,答案是1 但是,我的方法的复杂度为O(N^2)。我的方法的问题是复制数组需要O(N)时间。因此,我正在寻找另一种更有效的方法。空间复杂度对我来说并不重要。因为我正在学习字符串处理算法,如果我能自己实现这个算法会更好 任何帮助都将不胜感激 我的方法 tmp = [0] * 26 # 26 alphabet occurrences_table = [] tmp[ord(a_string[0])]

给定未排序的字符串,例如“googol”。我想找出[1,3]范围内字符“o”的出现次数。因此,在本例中,答案是1

但是,我的方法的复杂度为O(N^2)。我的方法的问题是复制数组需要O(N)时间。因此,我正在寻找另一种更有效的方法。空间复杂度对我来说并不重要。因为我正在学习字符串处理算法,如果我能自己实现这个算法会更好

任何帮助都将不胜感激

我的方法

tmp = [0] * 26  # 26 alphabet
occurrences_table = []
tmp[ord(a_string[0])] += 1
occurrences_table.append(tmp)
for i in range(1, len(a_string)):
    temp = occurrences_table[i - 1]
    temp[ord(a_string[i])] += 1
    occurrences_table.append(temp)

如果可以使用标准库:

>>> from itertools import islice
>>> from collections import Counter
>>> Counter(islice('googol', 1, 3))
Counter({'o': 2})
>>> Counter(islice('googol', 0, 2))
Counter({'g': 1, 'o': 1})
islice
避免临时列表。)

如果要手动执行此操作,请执行以下操作:

>>> s = 'googol'
>>> counter = dict()
>>> for i in range(0, 2):
...     if s[i] not in counter:
...         counter[s[i]] = 1
...     else:
...         counter[s[i]] += 1
... 
>>> counter
{'g': 1, 'o': 1}

要点是:如果您可以使用标准库,请使用
dict

>>> from itertools import islice
>>> from collections import Counter
>>> Counter(islice('googol', 1, 3))
Counter({'o': 2})
>>> Counter(islice('googol', 0, 2))
Counter({'g': 1, 'o': 1})
islice
避免临时列表。)

如果要手动执行此操作,请执行以下操作:

>>> s = 'googol'
>>> counter = dict()
>>> for i in range(0, 2):
...     if s[i] not in counter:
...         counter[s[i]] = 1
...     else:
...         counter[s[i]] += 1
... 
>>> counter
{'g': 1, 'o': 1}
要点是:使用
dict

你可以使用:

导致

Counter({'o': 1, 'g': 1})
请注意,数组切片对字符串有效。

您可以使用:

导致

Counter({'o': 1, 'g': 1})

请注意,数组切片可以在字符串上工作。

因为您不想使用,也不想自己实现它,所以可以使用字典对代码进行整理并稍微加快速度

a_string = "googol"
my_counter = {}
for c in a_string[:2]:
    my_counter[c] = my_counter.get(c, 0) + 1
这将给你:

{'o': 1, 'g': 1}
进一步解释一下,
a_string[:2]
获取字符串中索引为2的字符(
'google'[:2]
=
'go'
)和a_string[:2]中c的
在这两个字符上循环

在下一行中,
my_counter.get(c,0)+1
尝试获取键“c”(字符串中的单个字符)的字典值,如果该键存在,则返回其值,如果不存在,则返回0,并将递增的值添加回字典


编辑:

由于for循环,复杂性应为O(n),因为
dictionary.get()
的复杂性是恒定的


我已经对它进行了测量,对于像您这样的非常小的字符串,此方法的速度是您的8-10倍,但是对于非常大的字符串,它的速度要慢2-3倍。

因为您不想使用并且希望自己实现它,所以您的代码可以通过使用字典进行整理并稍微加快

a_string = "googol"
my_counter = {}
for c in a_string[:2]:
    my_counter[c] = my_counter.get(c, 0) + 1
这将给你:

{'o': 1, 'g': 1}
进一步解释一下,
a_string[:2]
获取字符串中索引为2的字符(
'google'[:2]
=
'go'
)和a_string[:2]中c的
在这两个字符上循环

在下一行中,
my_counter.get(c,0)+1
尝试获取键“c”(字符串中的单个字符)的字典值,如果该键存在,则返回其值,如果不存在,则返回0,并将递增的值添加回字典


编辑:

由于for循环,复杂性应为O(n),因为
dictionary.get()
的复杂性是恒定的


我已经测量过了,对于像您这样的非常小的字符串,这种方法比您的方法快8-10倍,但是对于非常大的字符串,它慢2-3倍。

检查。您可以使用它来处理字符串的特定范围。@umutto。但这就像我正在学习一些字符串处理算法。所以我想自己实现这个算法@kevinnnluo-你真的应该在你原来的问题中提到这个限制。@Christian König。是的,我的错。我已经编辑了它。检查。你可以使用它来处理字符串的特定范围。@umutto。但这就像我正在学习一些字符串处理算法。所以我想自己实现这个算法。@kevinnnluo-你真的应该这样做吗我想在你的原始问题中提到这个限制。@Christian König。是的,我的错。我已经编辑了它。我想他的
范围[1,3)
-符号开始从位置1开始计算字符,直到并排除位置3-在python中非常有效[0:2]。谢谢你的回答。因为范围是[1,3],所以子字符串是“go”,只有一个“o”。但这就像我在学习字符串处理算法,所以我想自己实现它。是的,我意识到当我看到你回答时;)@kevinnnluo在python中的索引从0开始,这就是为什么我感到困惑。我想他的
范围[1,3)
-表示法从位置1开始计算字符,直到并排除位置3-在python中非常有效[0:2]。感谢您的回答。因为范围是[1,3],所以子字符串是“go”,它只有一个“o”。但这就像我在学习字符串处理算法,所以我想自己实现它。是的,我意识到当我看到你回答时;)@kevinnnluo python中的索引从0开始,这就是我感到困惑的原因。