Если целью является просто удалить общие символы на концах обеих строк, мы могли бы написать:
def remove_common_ending(str1, str2)
return ["", ""] if str1 == str2
n = [str1.size, str2.size].min
return [str1, str2] if n.zero?
i = (1..n).find { |i| str1[-i].downcase != str2[-i].downcase }
[str1[0..-i], str2[0..-i]]
end
remove_common_ending(str1, str2)
#=> ["Hello World", "Good Bye"]
Другая возможная интерпретация заключается в том, что самую длинную общую подстроку необходимо удалить из обеих строк.Далее следует один из способов сделать это.Мой подход аналогичен @ tadman, за исключением того, что я начинаю с длины максимально длинной общей подстроки, затем постепенно сокращаю эту длину до тех пор, пока не будет найдена подстрока, которая появляется в обеих строках.Таким образом, нет необходимости искать более короткие подходящие подстроки.
def longest_common_substring(str1, str2)
return '' if str1.empty? || str2.empty?
s1, s2 = str1.downcase, str2.downcase
(s1, s2 = s2, s1) if s2.size < s1.size
sz1 = s1.size
sz1.downto(1) do |len|
puts "Checking #{sz1-len+1} substrings of length #{len}..."
(0..sz1-len).each do |i|
s = s1[i, len]
return s if s2.include?(s)
end
end
end
Я добавил оператор puts
, чтобы показать, какие вычисления выполняются.Обратите внимание, что я ищу в более длинной строке (str1
) подстроки более короткой строки (str2
).
str1 = "Hello World: This is a test message"
str2 = "Good Bye: This is a test message"
s = longest_common_substring(str1, str2)
Checking 1 substrings of length 32...
Checking 2 substrings of length 31...
Checking 3 substrings of length 30...
Checking 4 substrings of length 29...
Checking 5 substrings of length 28...
Checking 6 substrings of length 27...
Checking 7 substrings of length 26...
Checking 8 substrings of length 25...
Checking 9 substrings of length 24...
#=> ": This is a test message"
r = /#{Regexp.escape(s)}/i
#=> /:\ this\ is\ a\ test\ message/i
str1.sub(r,'') #=> "Hello World"
str2.sub(r,'') #=> "Good Bye"
Как видно, количество подстрок более короткой строки (str2
), котороебыли проверены до того, как была найдена самая длинная общая подстрока (1+10)*10/2-1 #=> 54
.