Algorithm 根据集合范围检查子集的有效算法

Algorithm 根据集合范围检查子集的有效算法,algorithm,set,subset,Algorithm,Set,Subset,我通读了一些关于确定一组a是否是另一组B的子集的帖子。但我发现很难决定使用什么算法。以下是问题的概要: 我有一个字符串数组A,我在程序开始时收到它。关于这个结构,我们知道的不多。数组中的每个字符串可以任意长,并且条目的数量不受限制。虽然通常可以假设数组中的条目数不会太大(

我通读了一些关于确定一组
a
是否是另一组
B
的子集的帖子。但我发现很难决定使用什么算法。以下是问题的概要:

  • 我有一个字符串数组
    A
    ,我在程序开始时收到它。关于这个结构,我们知道的不多。数组中的每个字符串可以任意长,并且条目的数量不受限制。虽然通常可以假设数组中的条目数不会太大(<100)
  • 然后我遍历长度为
    n
    的对象列表
  • 每个
    n
    对象还将有一个字符串数组
    B
    ,即将有
    n
    B
    数组。一旦程序运行,
    B
    s将被修复,即它们在运行期间不会改变
  • 我想确定每个对象的
    A
    是否是
    B
    的子集
现在,我想到了哈希表。然而,在我看来,它们只有在只有一个
B
和大量
a
s的情况下才会有效。然后我可以为
B
创建一个哈希表,并对照哈希表检查每个对象的每个字符串数组。但事实并非如此,因为只有一个
A
而只有
n
B
s。要做到这一点,什么是有效的算法

例如:

A:  ["A", "G", "T"]
B1: ["C", "G"]
B2: ["K", "A", "U", "T", "G"]
.
.
.
Bn: ["T", "I", "G", "O", "L"]

这里
A
B2
的子集,但不是
B1
的子集,也不是
Bn

的子集,正如您事先所知
A
的所有元素都可以散列

然后只对搜索步骤中的哈希值进行操作,而不是对字符串进行操作。对于B的每个元素,计算其哈希值,然后使用它查找A的一个元素。如果找到一个元素,则表示哈希值匹配;然后,您还需要比较字符串,以检测它是真的正匹配还是偶然匹配


计算匹配的数量。当该数字等于A的大小时,停止并返回一个正结果。如果a B的所有元素都已处理,且匹配数小于a的大小,则返回一个负结果。

作为第一种方法,我将预先计算集合的一些一般属性,这(希望)将允许您快速筛选一些
B
s。例如,这些可能是:

  • 大量字符串–
    a
    当然不能是
    B
    的子集,如果它包含的元素多于
    B
  • 最长字符串的长度–
    a
    当然不是
    B
    的子集,如果
    a
    中的最长字符串比
    B
    中的最长字符串长
  • 字符串长度的总和
为了便于检查,您可能需要按字母顺序对每个集合进行排序。这将允许在(线性)扫描两组字符串时,针对单个
B
检查
A


对于小型
A
和大型
B
集合,使用二进制搜索而不是线性扫描在
B
中查找字符串可能更有效;这也需要对
B
进行预排序。

一种有效的方法是将集合A表示为trie。这允许检查给定字符串是否属于字符串长度中的时间线性

那么,没有更好的方法可以彻底检查所有Bi和Bi中的所有字符串(如果它属于A)。一旦A中的所有字符串都匹配,搜索就会停止(在找到字符串时标记该字符串)

运行时间将与所有B中所有字符串中的字符总数成更差的比例。在实践中,将跳过很大一部分字符,如下所示:

  • 对不在中的字符串的搜索可以提前终止

  • 即使Bi中还有字符串,子集测试也可以得出肯定结论

  • 当A中的不匹配字符串多于Bi中的剩余字符串时,子集测试可能得出否定结论


这种方法在最坏情况下当然是最佳的,因为您最多读取一次字符,并对每个字符执行固定数量的操作。

您需要多久检查一次a中的某个字符串是否是B的子字符串?您的程序是否运行了很长一段时间,在此期间,您多次检查相同的字符串列表a以查找(可能已更改)B?在每次运行程序时,
a
在开始时是固定的。
B
在程序运行期间也是固定的。它们不会改变。但是有很多
B
s.“而B因对象而异”,所以如果B是固定的,那意味着什么呢。你能编辑你的答案并发布一些A和B的示例数据吗?关于字符串长度的分布,你能告诉我们什么?(在你的例子中,它们都是1。)对不起,我对这个答案不满意。字符串是短的、长的还是很长的(1兆字符)?都是吗。。。如果B中的元素是A的严格超集,您将如何检测A是B中元素的子集?“他们的哈希值不会是一样的,对吧?”格鲁布斯:哦,我误解了这个问题。更新了现在描述简单算法的答案。我认为有可能做得更好。是的,我现在明白你的意思了,这更有意义。我很喜欢CiaPan提出的二进制搜索的想法,如果A比B小很多,搜索可能比遍历整个列表更有效。所有这些预计算都应该在实际算法以某种启发式形式运行时进行,因为在运行某些算法之前,需要对潜在的大输入进行多个循环。此外,如果A比B中的任何元素小得多,二进制搜索也会非常简洁。@Glubus所有这些参数只需要对每个集合进行一次扫描,对每个字符串只进行一次长度测试,因此它会产生严格的线性时间开销和最小的内存