Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 有效地从集合D中包含的集合C中查找所有集合S_Algorithm_Scala_Set_Subset - Fatal编程技术网

Algorithm 有效地从集合D中包含的集合C中查找所有集合S

Algorithm 有效地从集合D中包含的集合C中查找所有集合S,algorithm,scala,set,subset,Algorithm,Scala,Set,Subset,我从目标集的集合C开始。每组包含单词(或不带空格的字符串)。当我重复句子时,我可以把这个句子看作是一组观察到的单词 d>代码>。我的问题是,对于每个句子,我想在C中找到所有S,这样D包含S。换句话说,我想找到C中的所有单词集,它们的所有单词都在句子中 例如,考虑 C>代码>以下内容: {fell, ate} {cat, snail, tiger} {tree, bush, jalepeno} {pen, paperclip, stapler} 现在,如果我看到“树倒在灌木丛上,

我从目标集的集合
C
开始。每组包含单词(或不带空格的字符串)。当我重复句子时,我可以把这个句子看作是一组观察到的单词<代码> d>代码>。我的问题是,对于每个句子,我想在
C
中找到所有
S
,这样
D
包含
S
。换句话说,我想找到
C
中的所有单词集,它们的所有单词都在句子中

例如,考虑<代码> C>代码>以下内容:

  {fell, ate}
  {cat, snail, tiger}
  {tree, bush, jalepeno}
  {pen, paperclip, stapler}
现在,如果我看到“树倒在灌木丛上,因为它吃了一瓶杰莱普诺”,我想退回以下两套

  {fell, ate}
  {tree, bush, jalepeno}
这似乎有点类似于trie。然而,它只是相似,因为我没有匹配句子中的所有单词,而是匹配任何子集。一个想法是在每个级别用
Map[String,PseudoTrie]
以类似trie的数据结构表示集合
C
,并在我按排序顺序迭代句子中的单词时遵循多条路径

我知道这类似于搜索查询。但是,如果我需要迭代所有的句子,只要每个句子的计算速度很快就可以了。在
C
中迭代每个集合并执行包含操作太慢

更新

我想人们可能会对我的一些成果感兴趣。这些计时是在100000句句子上进行的,而
D
中的每个目标集
C
大约有4到5个单词

  • 原始申请。迭代所有目标集,查看它们是否包含在句子中,其中句子由一组单词表示。227 s

  • 按词汇过滤。与原始过程相同,不同的是句子由该句子中的一组词表示,这些词也在某个目标集中。优点是我们只需要在比较时考虑句子中的一个词的子集。110秒

  • 字符串转换为从0开始的整数键。这还包括根据需要在试验2中进行过滤。86秒

  • 添加反向索引。4秒

  • 我还尝试了带反转索引的位集。花了20秒,所以我没有坚持。我不确定经济放缓的原因——我可能做错了什么


    此外,我认为我最初的想法很好(许多层的反向索引),但它相当复杂,我已经有了相当好的加速

    我们将从您要搜索的句子语料库开始:

    val corpus = Seq(
      Set("fell", "ate"),
      Set("cat", "snail", "tiger"),
      Set("tree", "bush", "jalapeno"),
      Set("pen", "paperclip", "stapler")
    )
    
    一种相当有效的表示方法是将其表示为一个位表,词汇类型作为列,句子作为行。我们定义了两个用于转换为该表示形式的函数:

    import scala.collection.immutable.BitSet
    
    def vocabulary(c: Seq[Set[String]]) = c.reduce(_ union _).zipWithIndex.toMap
    
    def convert(s: Set[String], v: Map[String, Int]) = (BitSet.empty /: s) {
      (b, w) => v.get(w).map(b + _).getOrElse(b)
    }
    
    以及一个功能,用于在语料库
    c
    中搜索给定句子
    s
    包含的所有句子:

    def search(s: BitSet, c: Seq[BitSet]) = c.filter(x => (x & s) == x)
    
    这将非常快,因为它只是一个按位“and”和语料库中每个句子的相等比较。我们可以测试:

    val vocab = vocabulary(corpus)
    val table = corpus.map(convert(_, vocab))
    
    val sentence = convert(
      "The tree fell over on the bush because it ate a jalapeno".split(" ").toSet,
      vocab
    )
    
    val result = search(sentence, table)
    
    这给我们提供了
    列表(位集(2,6),位集(5,7,10))
    。为了确认这是我们想要的:

    val bacov = vocab.map(_.swap).toMap
    result.map(_.map(bacov(_)))
    

    这是所需的
    列表(Set(fall,ate),Set(jalapeno,tree,bush))

    您通常可以通过创建一个字典,为每个单词指定一个数字,然后从字符串之间的比较切换到数字之间的比较来加速基础比较

    一个简单的方法是从每个集合中随机选取一个单词,然后创建一个字典,将每个单词映射到一个集合列表,从中选择单词。然后,给定一个句子,在字典中查找其中的每个单词,看看句子中是否包含任何集合列表

    您可能能够快速检测到集合何时不是句子的子集。为每个字创建一个稀疏的64位模式,并将每个集合表示为其中每个字的位模式的or。将一个句子表示为其所有单词的或。那么如果设置&~语句!=0,则该集合不包含在句子中。如果某个集合未通过此测试,则该集合不是子集。不幸的是,如果它通过了测试,它可能仍然不是一个子集,您将不得不使用较慢的测试来确认这一点,但是如果在第一个关卡上有足够多的集合失败,您可以节省时间。根据经验,我会让每个64位模式都有k个随机选择的位集,选择k使得代表句子的64位模式有大约一半的位集-但是你可能可以在信封背面稍微考虑一下,找到一个更好的目标。如果你只是在一个句子中找到一个特定的单词后才进行这个测试,你当然可以在你创建的集合中不包含这个单词,把它的出现视为理所当然

    假设一个单词独立设置64位位图中的每一位,但未能以概率x设置它。然后,在一个包含n个单词的句子中,位图中没有为该句子设置一个位,概率为x^n。对于一个有k个单词的集合,如果它是由句子而不是由单词设置的,我们可以根据该位进行丢弃,概率为(1-x^k)x^n。如果我对此进行微分,我会在x=(n/(n+k))^(1/k)处得到一个最大值。如果我设置n=20k=4,那么我想要x=0.9554,一个句子中的位大约40%的时间是清晰的,一个位大约7%的时间是丢弃的。但是我们有64位,它们在这个模型上几乎是独立的,所以我们在98%的时间里丢弃了完全的不匹配。

    An对于这类问题非常有用。作为一个起点,考虑创建一个从“代码> C <代码>中的单词映射到包含该单词的所有集合的列表,从而具有类型<代码> MAP[String,List[St[Str] ] ] < /代码>;这是反向索引

    使用反向索引,您可以找到
    D
    中包含的集合,而无需检查