我认为以上的答案都忽略了关键点。我们有一个27维的空间,第一维是长度,其余的是每个字母的坐标。在这个空间中,我们有点,这些点就是单词。一个单词的第一个坐标是它的长度。其他坐标是每个字母出现的次数。例如单词abacus, deltoid, gaff, giraffe, microphone, reef, qar, abcdefghijklmnopqrstuvwxyz的坐标如下:
[3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[6, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]
[7, 0, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[4, 1, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[7, 1, 0, 0, 0, 1, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[10, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[4, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
一个带有坐标的集合的良好结构是R树或R*-树。给定你的集合[x0, x1, ..., x26],你需要查询包含最多xi个字母的所有单词,对于每个字母。你的搜索时间复杂度为O(log N),其中N是字典中单词的数量。然而,你不想查看与查询匹配的所有单词中最长的单词。这就是为什么第一维很重要。
你知道最长单词的长度在0到X之间,其中X=sum(x_i, i=1..26)。你可以从X到1进行迭代搜索,但也可以使用二分查找算法来查询长度。你将数组的第一维用作查询。你从a=X开始到b=X/2。如果至少有一个匹配项,你就从a到(a+b)/2进行搜索,否则你就从b到b-(a-b)/2=(3b-a)/2进行搜索。你重复这个过程直到b-a=1。现在你已经得到了最大长度和所有与该长度匹配的结果。
这个算法的时间复杂度比上面的算法要高效得多。时间复杂度为O(ln(N)×ln(X))。具体实现取决于你使用的R-tree库。