计算给定字符串的所有子字符串中出现的元音数量

Count the number of vowels occurring in all the substrings of given string

我正在看这个挑战:

Given a string of length N of lowercase characters containing 0 or more vowels, the task is to find the count of vowels that occurred in all the substrings of the given string.

Example

Input: str = "abc" 
Output: 3

The given string "abc" contains only one vowel = 'a'. Substrings of "abc" are

{"a", "b", "c", "ab", "bc", "abc"}

Hence, the sum of occurrences of the vowel(s) in these strings is:

3 

('a' occurred 3 times).

如何在O(N)时间复杂度下解决上述问题?

以下是算法中要使用的一些元素:

让我们先数一数可以从一个字符串中形成多少子串(忽略元音计数):

"a" => {"a"} => 1
"ab" => {"ab", "a", "b"} => 1+2 = 3
"abc" => {"abc", "ab", "bc", "a", "b", "c"} => 1+2+3 = 6
"abcd" => {"abcd", "abc", "bcd", "ab", "bc", "cd", "a", "b", "c", "d"} => 1+2+3+4 = 10
 ...

模式为1+2+3+...+,其中为字符串的长度,即(+1)/2

现在我们来看一个只有 一个 元音的字符串:“klmnopqrst”。然后答案包括计算具有该元音的子串的数量。

我们知道总共有 10(10+1)/2 = 55 个子串,但其中许多子串没有元音。 None 个“klmn”的子串有一个元音。有 4(4+1)/2 = 10 个这样的子串。 “pqrst”的 none 个子串也有一个元音。有 5(5+1)/2 = 15 个这样的子串。所有其他子串都有元音。所以我们可以做减法...输出应该是 55 - 10 - 15 = 30.

因此,一般原则是:对于输入中的每个元音,确定有多少子串包含该元音——通过计算 [=31] 处的子串数量=]左,以及元音处的那些。这为我们提供了有关 do 包含该元音的子字符串数量的线索——通过从子字符串总数中减去非大小写。

如果我们对每个元音都这样做,我们将计算出所有子字符串中元音的总出现次数。

这是用伪代码表示的算法:

function occurrence(str):
    n := length(str)
    total := 0
    allcount := n * (n + 1) // 2
    for i := 1 to n:
        if str[i] is a vowel:
            total = total + allcount - (i - 1) * i / 2 - (n - 1 - i) * (n - i) / 2
    return total

注意:请注意——正如在伪代码中常见的那样——i 是一个 position(从 1 开始),而不是从零开始的索引。

(以防不够用。)

每个元音出现在 (l + 1) * (r + 1) 个子字符串中,其中 l 是元音左侧的字符数,r 是元音右侧的字符数。

Example 1:

"abc"

'a': (0 + 1) * (2 + 1) = 3

Total: 3


Example 2:

"ae"

'a': (0 + 1) * (1 + 1) = 2
'e': (1 + 1) * (0 + 1) = 2

Total: 4