Пока я не узнал о «самой длинной общей проблеме подстрок / последовательностей» (см. Ответ @ Dustin), я не думал, что есть подход, который лучше, чем тот, который вы обрисовали в вопросе: начните с максимально возможного подмассива (array2
), затем последовательно уменьшайте размер подмассивов на единицу, пока не будет найдено совпадение (или определено, что два массива не содержат общего элемента).Хотя теперь я вижу, что есть более эффективный способ, ваша идея, безусловно, неплохая, особенно если подстроки не слишком велики, и их легче реализовать, чем решение для динамического программирования, на которое ссылается Дастин.Я реализовал вашу идею ниже.
Я решил использовать регулярное выражение для определения совпадений, поэтому мне нужно преобразовать array1
в строку.
str1 = array1.join(' ')
#=> "hello world i am in the world"
Расчет выполняется следующим образом.
[array1.size, array2.size].min.downto(1).each do |n|
a = array2.each_cons(n).find { |a| str1.match?(/\b#{a.join(' ')}\b/) }
break a unless a.nil?
end
#=> ["hello", "world"]
nil
возвращается, если array1
и array2
не имеют общего элемента.При желании можно сначала проверить (array1 & array2).empty?
.
Вот возможное улучшение того, что у меня есть выше.Идея состоит в том, чтобы попытаться уменьшить m
в m.downto(1)
.
h1 = array1.each_with_object(Hash.new(0)) { |word, h| h[word] += 1 }
#=> {"hello"=>1, "world"=>2, "i"=>1, "am"=>1, "in"=>1, "the"=>1}
h2 = array1.each_with_object(Hash.new(0)) { |word, h| h[word] += 1 }
#=> {"hello"=>1, "world"=>2, "i"=>1, "am"=>1, "in"=>1, "the"=>1}
m = [array1.size, array2.size, h2.sum { |k,v| [v, h2[k]].min }].min
#=> [7, 6, 7].min
#=> 6
Здесь это не поможет, но возможно, если бы массивы array1
и array2
были разными.