计算ruby中子串列表出现次数的最快方法

时间:2014-05-02 11:40:52

标签: ruby algorithm optimization substring

我的问题很简单,我有一个子串列表,我必须计算特定字符串中包含的子串数。 这是我的代码:

string = "..."
substrings = ["hello", "foo", "bar", "brol"]
count = 0
substrings.each do |sub|
    count += 1 if string.include?(sub)
end

在这个例子中,我们遍历整个字符串4次,这非常消耗。 你会如何优化这个过程?

2 个答案:

答案 0 :(得分:7)

这只使用Regexp.union来运行字符串一次:

string = 'hello there! this is foobar!'
substrings = ["hello", "foo", "bar", "brol"]

string.scan(Regexp.union(substrings)).count
# => 3

虽然此解决方案在输入较小时明显较慢,但其复杂度较低 - 对于长度为n的字符串和长度为m的子字符串,原始解决方案的复杂度为O(m*n),而此解决方案的复杂性为O(m+n)


<强>更新
在再次阅读问题和我的回答之后,我得出的结论是,不仅这是一个不成熟的优化(正如@Max所说),但我的答案在语义上与不同而不是OP

让我解释一下 - OP代码计算字符串中substrings有多少至少一个外观,而我的解决方案计算多少次出现有{em>任何的substrings

op_solution('hello hello there', ["hello", "foo", "bar", "brol"])
# => 1
uri_solution('hello hello there', ["hello", "foo", "bar", "brol"])
# => 2

这也解释了为什么我的解决方案速度太慢,即使对于长字符串 - 尽管输入字符串只有一个传递,但它必须传递所有,而原始代码停在第一次出现一个单词。

我的结论是 - 使用@Arup的解决方案。它不会比你的更快,它只是更简洁,但我想不出更好的东西:)

答案 1 :(得分:3)

写作: -

substrings.count { |sub| string.include?(sub) }