Suppose dict
是你的字典和的字符串数组scrambled
是一个乱码词(字符串)。考虑所有排列scrambled
或(更糟糕)的元素dist
将是非常低效的。例如,假设一个乱序排列的前两个字母是qz
。如果其中没有元素(单词)dict
那开始qz
,没有必要考虑任何排列scrambled
那开始qz
.
数据结构
假设这是我们的字典。
dict = ["dog", "cat", "cow", "emu", "cod", "cobra"]
如果我们只想查看字典中是否有一些乱序的单词,我们可以对每个单词执行以下操作:
r = 'mue'.split('').permutation(3).find { |w| dict.include?(w.join) }
#=> ["e", "m", "u"]
r.any? ? r.join('') : nil
#=> "emu"
r = 'nvwls'.split('').permutation(3).find { |w| dict.include?(w.join) }
#=> nil
更有趣的问题是如何以更有效的方式做到这一点,以检查大量具有多种排列的可能较长的单词。
第一步是重新组织字典以提高查找效率。我不是建议如何做到这一点的最佳人选,因为我不熟悉计算机科学的那个(或任何其他)分支。这是一种使用多级哈希的方法:
dh = { "c"=>{ "a"=>{ "t"=>nil },
"o"=>{ "b"=>{ "r"=>{ "a"=>nil } }, "w"=>nil, "d"=>nil } },
"d"=>{ "o"=>{ "g"=>nil } },
"e"=>{ "m"=>{ "u"=>nil } } }
dh["c"]
“包含”所有以“c”开头的单词;dh["c"]["a"]
包含所有以“ca”开头的单词,依此类推。dh["c"]["a"]["t"] => nil
意味着dh["c"]["a"]["t"].join('') => 'cat'
是字典中的单词之一。我假设你有dh
。如果您想了解如何构建的建议dh
from dict
,也许你可以将其作为一个单独的问题来问。
Code
这是一个(递归)方法,可用于查看是否有任何解读scrambled
包含在dict
。 (修改它来编译在中找到的所有排列的列表并不困难dict
,但这不是我解决的问题。)此方法的调用方式为look_up(dh, scrambled)
.
def look_up(dh, left, used = '')
left.size.times do |i|
left_copy = left.dup
e = left_copy[i]
left_copy[i] = ''
v = dh[e]
case v
when nil
(return used + e) if left_copy.empty?
when Hash
word = look_up(v, left_copy, used + e)
return word if word
end
end
nil
end
Example
look_up(dh, "owc") #=> "cow"
look_up(dh, "mue") #=> "emu"
look_up(dh, "bocar") #=> "cobra"
look_up(dh, "esuomhcruhc") #=> nil
解释
Suppose dh
如上所述并且scrambled => "owc"
. Then
left = "owc"
used = ''
left.size #=> 3
enum = left.size.times #=> #<Enumerator: 3:times>
我们可以转换enum
到一个数组以查看它将传递给其块的内容:
enum.to_a #=> [0, 1, 2]
最初,块变量i
被设定为0
and
left_copy = left.dup #=> "owc"
e = left_copy[i] #=> left_copy[0] => "o"
left_copy[i] = '' #left_copy[i] = ''
left_copy #=> "wc"
v = dh[e] #=> v = dh[0] => nil
dh[0] => nil
,结合left_copy.empty? => false
,表示字典中没有以“o”开头的单词,因此我们返回循环顶部并设置i => 1
并考虑以'o'
:
left_copy = left.dup #=> "owc"
e = left_copy[i] #=> left_copy[1] => "w"
left_copy[i] = '' #=> left_copy[1] = ''
left_copy #=> "oc"
v = dh[e] #=> v = dh[1] => nil
字典里没有开头的单词'w'
,所以我们再次循环i => 2
,
searching for words in the dictionary beginning with `'c'`:
e = left_copy[2] #=> "c"
left_copy[2] = '' #=> left_copy[2] = ''
left_copy #=> "ow"
v = dh[2] #=> {"a"=>{"t"=>nil},
# "o"=>{"b"=>{"r"=>{"a"=>nil}}, "w"=>nil, "d"=>nil}}
这说明字典中有开头的单词'ca`` and
'co'`.
As v
是一个散列,我们递归地调用该方法
word = look_up(v, left_copy, used + e)
# look_up({"a"=>{"t"=>nil},
# "o"=>{"b"=>{"r"=>{"a"=>nil}}, "w"=>nil, "d"=>nil}},
# "ow",
# "c")
对于其他字母,计算过程类似。当发现字典中有该字符串的单词时"co"
代表者:
{ "b"=>{ "r"=>{ "a"=>nil } }, "w"=>nil, "d"=>nil }
我们得出结论,因为这个哈希包含"w"=>nil
, that "cow"
在字典中,所以我们返回'cow'
沿着递归链向上并完成。