这是困扰我一段时间的问题。假设字符串是1和0 的序列,通配符字符串是1、0和?s的序列。所有字符串和通配符字符串具有相同的长度。这些是标准的UNIX通配符。10 ?? 1匹配10011、10111等-a?在该位置匹配1或0。如果和是通配符字符串,那么如果与匹配的每个字符串也与匹配,则我们写。
问题:给定一组通配符字符串和一个查询(也是通配符字符串),是否存在使得吗?如果不是,我们可以有效地将添加到吗?
这是显而易见的解决方案(其中是字符串的大小,是RAM的字大小(通常为32或64)):遍历列表中的每个元素并进行测试条件(可以使用位旋转2或3个操作来完成)。还要在扫描时测试是否适合任何。如果未能通过我们的测试,则将添加到集合中,并删除我们标记的。
但这还不够快。如果有解决方案,或者在理想情况下,复杂度类似于基数树(),那真的很酷。查询大致正确也可以:即,如果,则返回yes或no;否则,返回false。但是如果条件不成立,则绝对不返回。
尽管这并不能解决最坏的情况,但是您可以假定中的所有元素都由通配符字符串限制;也就是说,存在一些,使得对于所有,。
我尝试过的想法
- 通配符字符串形成联接符号。我们可以有一棵包含通配符字符串的n元树;叶子将是通配符字符串,分支将代表所有子代的联接。如果查询和联接是不可比拟的,那么我们不必浪费时间尝试与该分支的所有子代进行比较。此外,如果我们进行更新,而该更新恰好大于联接,则可以简单地删除整个分支。不幸的是,在最坏的情况下,这仍然是,并且在遍历树中添加元素时,我们并不总是找到建立的“最佳”联接。
- 一个可以形成的基数树根。我们知道由一些通配符字符串限制;假设它是0到0。然后,特里树的所有分支只需位于字符串的第1位和第3位。如果查询的当前位是1,则必须检查?。1个分支;如果为0,我们检查?0个分支;如果是?,我们只检查?。科。因为我们必须潜在地采取多个分支,所以这看起来不太好(出于相同的原因很难更新trie)。由于匹配是非常快速的操作,因此与幼稚的策略相比,在树中进行大量遍历会比较麻烦(遵循一堆指针比进行一些OR和AND的代价高得多)。
相关工作
在网络社区中,此问题表现为“数据包分类”,这是对已知算法和数据结构的良好概述。不幸的是,几乎总是假设通配符字符串仅匹配前缀,并且查询是此类字符串的元组。当然,我们总是可以转换通用通配符字符串来满足以下条件:1?00?1 ?? 是(1,?,0,0,?,1,?,?)。但是,这将是无效的。做出的另一个假设是,这些元组与“颜色”相关联,并且查询应返回颜色(不仅仅是匹配的颜色)。这使问题变得更加困难,因为我们必须对元组进行排序(否则,(0,?)和(?,1)中的哪一个与(0,1)相匹配是模棱两可的)。
在算法社区中,我发现了很多与查找与“无关”匹配的子字符串相关的结果。这是一个相当困难的问题,我无法真正利用任何技术。
结论
谢谢你的帮助!