在给定子集

时间:2016-10-26 11:14:17

标签: database algorithm data-structures rdbms

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

有人通过插入以下单词来填充数据库:

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

现在我的子集就是这个:

"cabd"

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

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

我们来解释一下:

  • “ab”和“ac”应位于顶部(我不关心在这种情况下哪一个首先出现)因为我的子集包含了这个词中的所有字符。
  • “abcde”是第三个,因为我拥有除“e”之外的所有内容,所以我只缺少 1 char
  • “def”之后出现因为我缺少 2 字符(“e”和“f”)的字符
  • “xyz”结尾,因为我没有任何字符

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

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

强力解决方案是在不同的表中存储char-word关系。所以要存储包含特定字符的所有单词id:

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

其中ID是:

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

正如您所看到的,使用此方法,算法将为我提供数千个查询和订购所需的结果,因此它不可扩展。有没有其他解决方案或智能方法来解决这个问题?

1 个答案:

答案 0 :(得分:1)

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

这是一个想法:

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

然后,您可以在该表上创建一个触发器,以便只要在该表中插入新单词,就会计算并存储此整数。

然后,对于给定的输入字X,您还将计算该整数。要获得正确的顺序,您将对表中的每个整数执行此整数的按位OR,并计算结果中的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