database - 在给定子集的集合中查找最接近完成字符串

标签 database algorithm data-structures rdbms

假设我有一组单词,其中字符在 a-z 的集合中。我们还假设单词最长 10 个字符 并且该集合可以由所有组合 构建(没有排列,所以我不关心顺序)没有重复的此类字符。数据库中的集合一开始是空的,必须有人填充它。我对如何构建数据库以使其对该查询高效而言拥有完全的自由。让我们从一个例子开始。

有人通过插入这些词来填充数据库:

"ab"
"ac"
"abcde"
"def"
"xyz"

现在我的子集是这个:

"cabd"

我的查询/算法应该做的是,它应该返回按“完成”排序的单词列表。为了更清楚,上面的查询应该按顺序返回这些词:

"ab"
"ac"
"abcde"
"def"
"xyz"

让我们解释一下:

  • “ab”和“ac”应该在顶部(在这种情况下我不关心哪个先出现)因为我的子集包含这个词中的所有字符。
  • “abcde”是第三个,因为我拥有除“e”以外的所有单词,所以我只缺少 1 个字符
  • “def”稍后出现,因为我缺少单词的 2 个字符(“e”和“f”)
  • “xyz”在最后,因为我在其中没有任何字符

进一步观察:如您所见,我不关心顺序。如果我的子集查询是“abcd”,结果应该完全相同。

现在事情变得复杂了:每个单词都以 ID 作为主键存储在数据库中。理想的解决方案应该是算法应该打印 10 个(或有限数量的)ID,我将使用这些 ID 来自己查询单词。仅供引用,我正在使用 Firebase,所以目前我不能依赖 SQL

暴力解决方案是在不同的表中存储一个字符-词关系。因此,要存储包含特定字符的所有单词 ID:

a : {
    "id1",
    "id2",
    "id3",
    "id4",
    ....
}
b : {
    "id1",
    "id4",
    ....
}

ID 在哪里:

id1 : {
    "ab"
}
id2 : {
    "ac"
}
id3 : {
    "ad"
}
id4 : {
    "abc"
}

如您所见,通过这种方法,算法会提供数千个我需要查询和排序的结果,因此它不可扩展。有没有其他解决方案或聪明的方法来解决这个问题?

最佳答案

最佳解决方案可能取决于您使用的 SQL 引擎,因为某些引擎将具有解决某些所需步骤的功能。

这是一个想法:

在包含单词的表中,您可以添加一个整数 列来表示单词中出现的字母。一个整数有足够的位可用于存储字母表中每个字母的一位信息:1 表示对应的字母出现,0 表示不出现。因此需要 26 位来表示 a-z 范围内的字符。

然后您可以在该表上创建一个触发器,以便每当您在该表中插入一个新词时计算并存储该整数。

然后对于给定的输入词 X,您还将计算该整数。为了获得正确的顺序,您将对该整数与表中的每个整数执行按位或运算,并计算结果中的 1 位。 1 位越少,匹配越好。最少的 1 位数将对应于 X 的整数表示中的位数。在此之上计算的每一位表示表行中未出现在 X 中的字符。

这是在 MySql 中进行设置的脚本:

--/
create function bitset(str varchar(10)) returns int
begin
declare num int;
    set num = 0;
    while length(str) > 0 do
        set num = num | power(2, ord(str) - ord('a'));
        set str = substr(str, 2);
    end while;
    return num;
end
/

create table words (
    word varchar(10),
    bits int
);

create trigger ins_word before insert on words for each row
    set new.bits = bitset(new.word);

insert into words(word) values ('ab'), ('ac'), ('abcde'), ('def'), ('xyz');

select   word, 
         bits,
         bit_count(bitset('cabd') | bits) bitwise_or
from     words
order by 3;

最终查询使用自定义函数 bitset 和 MySql 中的原生函数 bit_count

最终查询的输出如下所示:

 word |    bits  | bitwise_or
------+----------+-----------
ab    |        3 |    4
ac    |        5 |    4
abcde |       31 |    5
def   |       56 |    6
xyz   | 58720256 |    7

关于database - 在给定子集的集合中查找最接近完成字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40260835/

相关文章:

python - 假设我有一个 Python 列表。按部分随机化它的最pythonic和最有效的方法是什么?

java - 在 DAWG 而不是 Trie 上使用 Aho-Corasick

c++ - 寻找子树的空间复杂度

java - 如何将元素添加到HashMap中的ArrayList

java - 在 Java 中处理大型字符串列表

java - 尝试检索多个 JDBC 结果

ruby-on-rails - Rails rake 数据库 :seed not creating objects that belong_to another object?

java - 带有 HashMap 的 ArrayList 与带有 Class 的 ArrayList

javascript - HTML5 应用数据库同步

mysql - 我可以使用表中的其他列作为外键吗