Если я понимаю, что нам дан массив dictionary
слов, не содержащих пробелов, и строку str
, и мы должны построить ha sh, ключи которого являются элементами dictionary
и чьи значения равны количество неперекрывающихся подстрок 1 из str
, для которых ключ является подстрокой. Возвращаемое значение ha sh должно исключать ключи, имеющие нулевые значения.
Этот ответ касается ситуации, когда в:
substrings(str, dictionary)
dictionary
велико, str
не слишком -large (значение которого я уточню позже) и эффективность важны.
Начнем с определения вспомогательного метода, цель которого станет ясной.
def substr_counts(str)
str.split.each_with_object(Hash.new(0)) do |word,h|
(1..word.size).each do |sub_len|
(0..word.size-sub_len).each do |start_idx|
h[word[start_idx,sub_len]] += 1
end
end
end
end
Для примера, приведенного в вопрос,
substr_counts("go going")
#=> {"g"=>3, "o"=>2, "go"=>2, "i"=>1, "n"=>1, "oi"=>1, "in"=>1, "ng"=>1,
# "goi"=>1, "oin"=>1, "ing"=>1, "goin"=>1, "oing"=>1, "going"=>1}
Как видно, этот метод разбивает str
на слова, вычисляет каждую подстроку каждого слова и возвращает ha sh, чьи ключи являются подстроками, а значениями - общее количество неперекрывающиеся подстроки во всех словах, содержащих эту подстроку.
Требуемый ha sh теперь можно построить быстро.
def cover_count(str, dictionary)
h = substr_counts(str)
dictionary.each_with_object({}) do |word,g|
g[word] = h[word] if h.key?(word)
end
end
dictionary = ["below", "down", "go", "going", "horn", "how", "howdy",
"it", "i", "low", "own", "part", "partner", "sit"]
cover_count("go going", dictionary)
#=> {"go"=>2, "going"=>1, "i"=>1}
Другой пример:
str = "lowner partnership lownliest"
cover_count(str, dictionary)
#=> {"i"=>2, "low"=>2, "own"=>2, "part"=>1, "partner"=>1}
Здесь
substr_counts(str)
#=> {"l"=>3, "o"=>2, "w"=>2, "n"=>3, "e"=>3, "r"=>3, "lo"=>2,
# ...
# "wnliest"=>1, "lownlies"=>1, "ownliest"=>1, "lownliest"=>1}
substr_counts(str).size
#=> 109
Здесь есть очевидный компромисс . Если str
является длинным, и особенно если он содержит длинные слова 2 , построение h
займет слишком много времени, чтобы оправдать экономию за счет отсутствия определения, для каждого слова в dictionary
, если это слово содержится в каждом слове str
. Однако, если стоит построить h
, общая экономия времени может быть значительной.
1. Под «неперекрывающимися» я подразумеваю, что если str
равно 'bobobo'
, оно содержит одну, а не две подстроки 'bobo'
.
2. substr_counts("antidisestablishmentarianism").size #=> 385
, неплохо.