【问题标题】:How do I remove the longest prefix that appears in an array?如何删除出现在数组中的最长前缀?
【发布时间】:2011-04-27 08:50:51
【问题描述】:

我有两个数组,searchtarget。我想找到search 的最长元素序列,它从search 的开头开始,并且在target 中也以相同的连续顺序出现。然后我想返回一份 target 的副本,其中删除了这些元素。

这里有一些例子:

search = [4, "apple", 6, "turnip"]
target = [5, "apple", 4, "orange"]
=> [5, "apple", "orange"]           # Delete [4], the longest matching
                                    # prefix of `search`.

search = [4, "apple", 6, "turnip"]
target = [5, "apple", 4, "apple"]
=> [5, "apple"]                     # Delete [4, "apple"], the longest matching
                                    # prefix of `search`.

search = [4, "apple", 6, "turnip"]
target = [5, "apple", 6, 7]
=> [5, "apple", 6, 7]               # Nothing was matched; don't delete anything.

执行此检查的最简洁方法是什么?

【问题讨论】:

    标签: ruby arrays algorithm


    【解决方案1】:

    如果您想要在 O(m.n) 中运行的简单解决方案,其中 m 和 n 是目标和搜索字符串的长度,Ni​​kita 的解决方案是一个很好的解决方案。

    如果需要,您可以通过稍微复杂的实现在线性时间内完成此操作。 您的问题非常类似于一般的字符串搜索问题。最有效的字符串搜索算法向后工作,因此它们擅长查找后缀(如果不完全匹配)。由于您需要前缀,因此您需要首先反转您的搜索和目标字符串。然后运行Boyer-MooreKMP 字符串搜索。这些算法的通常实现只会给你完全匹配。但稍作修改,您也可以记住最长的前缀匹配。完成后,您可以返回并在另一个线性通道中将其删除。

    【讨论】:

      【解决方案2】:

      我没有时间制定完整的解决方案,但我想说有两种方法:

      1. 使用一对外部迭代器 并行运行阵列。 有关于并行的教程 在互联网上迭代,或 查看《红宝石》的副本 具有 很好的描述

      2. 或者你可以循环 搜索数组,弹出项目 目标数组,直到 目标数组为空(在这种情况下 无论你在哪里搜索 是你的前缀),或者你得到 搜索数组的末尾(其中 情况下,它完全包含在 目标数组)。

      http://flylib.com/books/en/2.44.1.124/1/ 有一个很好的并行迭代方法

      【讨论】:

        【解决方案3】:

        嗯,这看起来足够简单和紧凑,并且不会影响复杂性

        s_index = 0
        result = target.select do |t|
          match = search[s_index] == t
          s_index += 1 if match
          !match
        end
        

        Array#select docs

        欢迎改进!
        此外,如果您的 search 数组可以包含 nil 值,则需要在此处进行边界检查 (s_index < search.length)。

        【讨论】:

          【解决方案4】:

          您可以使用类似下面的代码。但它绝对不是针对性能进行调整的。

          class Array
            def remove(start, length)
              length.times {delete_at start}
              self
            end
          end
          
          def remove(a,b)
            b.length.downto(1) do |len|
              index = a.each_cons(len).to_a.index b[0,len]
              return a.remove(index, len) if index
            end
            return a
          end
          
          search = [4, "apple", 6, "turnip"]
          target = [5, "apple", 4, "orange"]
          remove target, search
          

          【讨论】:

            猜你喜欢
            • 2012-01-26
            • 2012-02-01
            • 2014-10-13
            • 1970-01-01
            • 2012-07-31
            • 2017-01-23
            • 1970-01-01
            • 2023-03-22
            • 1970-01-01
            相关资源
            最近更新 更多