令 D 为字典。固定 m 和 n。我们可以将寻找 m × n 矩形的问题表述为约束满足问题(CSP)。
x i,1 …x i,n ∈ D ∀i ∈ {1, …, m}
x 1,j …x m,j ∈ D ∀j ∈ {1, …, n}
x i,j ∈ {A, …, Z} ∀i ∈ {1, …, m}, ∀j ∈ {1, …, n}
解决 CSP 的一种非常常见的方法是将回溯与约束传播相结合。粗略地说,回溯意味着我们选择一个变量,猜测它的值,然后用更少的变量递归地解决子问题,而约束传播意味着试图减少每个变量的可能性数量(可能为零,这意味着没有解决方案)。
例如,我们可以通过选择 x 1,1 =来开始一个 3 × 3 的网格Q
。
Q??
???
???
使用英语词典,x 1,2和 x 2,1的唯一可能性是U
(在拼字游戏“单词”之前)。
解决 CSP 的艺术是在回溯和约束传播之间取得平衡。如果我们根本不传播约束,那么我们只是在使用蛮力。如果我们完美地传播约束,那么我们就不需要回溯,但是一个本身解决 NP-hard 问题的传播算法运行起来可能相当昂贵。
在这个问题中,除非我们有良好的数据结构支持,否则在每个回溯节点使用大型字典会变得很昂贵。我将概述一种方法,该方法使用trie或DAWG快速计算前缀延伸到完整单词的字母集。
在每个回溯节点,我们分配的变量集是一个 Young 表。换句话说,在它上面和左边的变量被赋值之前,没有变量被赋值。在下图中,.
表示已分配变量,*
和?
表示未分配变量。
.....*
...*??
...*??
..*???
*?????
标记的变量*
是下一个被赋值的候选变量。有多个选择而不是每次都选择一个固定变量的好处是,一些变量排序可能比其他的要好得多。
对于每个*
,对 trie/DAWG 进行两次查找,一次查找水平方向,一次查找垂直方向,并计算接下来可能出现的字母集的交集。一种经典的策略是选择可能性最小的变量,希望我们更快地达到矛盾。我喜欢这种策略,因为当变量的可能性为零时,它会自然地修剪,而当变量的可能性为零时,它会自然地传播。通过缓存结果,我们可以非常快速地评估每个节点。