Смею предложить решение грубой силы, которое не очень изящно, но все же полезно в случае, если
- у вас есть большое количество предметов (создание регулярного выражения может быть проблемой)
- строка для анализа не ограничена двумя компонентами
- вы хотите получить все разбиения строки
- вы хотите только полный анализ строки, который охватывает от ^ до $.
Из-за моего плохого английского я не мог найти длинное личное имя, которое можно разделить несколькими способами, поэтому давайте проанализируем фразу:
word = "godisnowhere"
Словарь:
@dict = [ "god", "is", "now", "here", "nowhere", "no", "where" ]
@lengths = @dict.collect {|w| w.length }.uniq.sort
Массив @lengths
добавляет небольшую оптимизацию алгоритма, мы будем использовать его для сокращения подслов длины, которых нет в словаре, без фактического выполнения поиска в словаре.Массив отсортирован, это еще одна оптимизация.
Основной частью решения является рекурсивная функция, которая находит начальное подслово в данном слове и перезапускает для подслово хвоста.
def find_head_substring(word)
# boundary condition:
# remaining subword is shorter than the shortest word in @dict
return [] if word.length < @lengths[0]
splittings = []
@lengths.each do |len|
break if len > word.length
head = word[0,len]
if @dict.include?(head)
tail = word[len..-1]
if tail.length == 0
splittings << head
else
tails = find_head_substring(tail)
unless tails.empty?
tails.collect!{|tail| "#{head} #{tail}" }
splittings.concat tails
end
end
end
end
return splittings
end
Теперь посмотрим, как это работает
find_head_substring(word)
=>["god is no where", "god is now here", "god is nowhere"]
Я не тестировал его подробно, поэтому заранее прошу прощения:)