我有这个Ruby函数告诉我两个字符串是否“几乎”相等,也就是说,如果字符串中的所有字符都相同并且以相同的方式排序,除了一个。所以,例如,这些是相等的
equal
eual
但这些不是
eal
equal
(上面缺少两个字符)。所以在帮助下,我想出了这个
(lcs(a,b) == shortest && longest.length - shortest.length == 1)
其中las由
定义 def lcs(xstr, ystr)
return "" if xstr.empty? || ystr.empty?
x, xs, y, ys = xstr[0..0], xstr[1..-1], ystr[0..0], ystr[1..-1]
if x == y
x + lcs(xs, ys)
else
[lcs(xstr, ys), lcs(xs, ystr)].max_by {|x| x.size}
end
end
但是我的功能花费了相当长的时间。请注意我的基准
2.4.0 :011 > timing = Benchmark.measure { StringHelper.lcs("navesxkolsky|1227000", "navsxkolsky|1227000") }
=> #<Benchmark::Tms:0x007fa1753830d8 @label="", @real=21.341279999993276, @cstime=0.0, @cutime=0.0, @stime=0.030000000000000027, @utime=21.28, @total=21.310000000000002>
我在这里找不到可以让我的比较时间缩短到一秒钟而不是21秒的东西吗?
答案 0 :(得分:0)
试试这个。主要的想法是,如果方法是返回false
,它将在知道后立即返回,即使需要rudundant代码也是如此。 (如果删除了行return false if (sz1-sz2).abs > 1
,则下面的方法仍然有效。)
def equal_but_one?(str1, str2)
sz1 = str1.size
sz2 = str2.size
return false if (sz1-sz2).abs > 1
i = [sz1, sz2].max.times.find { |i| str1[i] != str2[i] }
return false if i.nil?
case sz1 <=> sz2
when 0
str1[i+1..-1] == str2[i+1..-1]
when -1
str2[i+1..-1] == str1[i..-1]
when 1
str1[i+1..-1] == str2[i..-1]
end
end
equal_but_one?('cat', 'cut') #=> true
equal_but_one?('bates', 'bats') #=> true
equal_but_one?('buss', 'bus') #=> true
equal_but_one?('cat', 'cat') #=> false
equal_but_one?('pig', 'pigs') #=> true
equal_but_one?('pig', 'pegs') #=> false
equal_but_one?('', '') #=> false
equal_but_one?('', 'a') #=> true
require 'benchmark'
Benchmark.measure { equal_but_one?("navesxkolsky|1227000", "navsxkolsky|1227000") }.real
#=> 1.6000005416572094e-05