【问题标题】:What is the faster way to search for sequence of numbers in a 2d vector?在二维向量中搜索数字序列的更快方法是什么?
【发布时间】:2019-03-13 00:10:51
【问题描述】:

给定一个具有整数值的二维数组(数组可以大于 10k*10k),在数组中搜索给定数字序列的更快方法是什么?

假设文件中的二维数组被读入一个大的一维向量,并以 big_matrix(row*x+width) 的形式访问。 我想在同一个二维数组上进行 3 种类型的搜索。它们是搜索有序、搜索无序、搜索最佳匹配。这是我对每个搜索功能的处理方法。

Search Ordered:此函数查找存在给定数字顺序(数字顺序很重要)的所有行。这是我实现的查找给定数字序列的 KMP 方法:

void searchPattern(std::vector<int> const &pattern, std::vector<int> const &big_matrix, int begin, int finish,
                         int width, std::vector<int> &searchResult) {

    auto M = (int) pattern.size();
    auto N = width; // size of one row

    while (begin < finish) {
        int i = 0;
        int j = 0;
        while (i < N) {
            if (pattern[j] == big_matrix[(begin * width) + i]) {
                j++;
                i++;
            }
            if (j == M) {
                searchResult[begin] = begin;
                begin++;
                break;
            } else if (i < N && pattern[j] != big_matrix[(begin * width) + i]) {
                if (j != 0)
                    j = lps[j - 1]; // lookup table as in KMP
                else
                    i = i + 1;
            }
        }
        if (j != M) {
            searchResult[begin] = -1;
            begin++;
        }
    }
}

复杂度:O(m*n); m是行数,n是列数

搜索无序/搜索最佳匹配:此函数查找存在给定数字序列的所有行(数字顺序无关紧要)。 在这里,我最初对大数组进行排序,并且在搜索期间仅对输入数组进行排序。

void SearchUnordered/BestMatch(std::vector<int> const &match, std::vector<int> const &big_matrix_sorted, int begin, int finish,
                     int width, std::vector<int> &searchResult) {
    std::vector<int>::iterator it;
    std::vector<int> v(match.size() + width);
    while (begin < finish) {
        it = std::set_intersection(match.begin(), match.end(), big_matrix_sorted.begin() + begin * width,
                                   big_matrix_sorted.begin() + begin * width + width, v.begin());
        v.resize(it - v.begin());
        if (v.size() == subseq.size())
        searchResult[begin] = begin;
        else
        searchResult[begin] = -1;
        begin++;
        /* For search best match the last few lines will change as follows:
      searchResult[begin] = (int) v.size();
      begin++; and largest in searchResult will be the result */
    }
}

复杂度:O(m*(l + n)); l - 模式的长度,m是行数,n是列数。

big_matrix 的预处理(构建查找表,存储它的排序版本。您可以进行任何预处理。)不考虑 .如何提高这些搜索函数的复杂度(到 O(log (m*n))?

【问题讨论】:

  • "假设文件中的二维数组被读入一个大的一维向量并作为 big_matrix(rowx+width)"* - 如果我们可以假设那么我认为这只是一个1d数组问题。
  • @Galik 你可以这样想,但你必须返回与搜索条件匹配的行索引。
  • 我认为缓慢的部分将是搜索。从绝对偏移量中发现行和列的数学运算将在百万分之几秒内发生。你试过std::search吗?您可能会从使用 boyer_more_searcher 中受益。
  • @Galik 是的,我已经尝试过std::search,但我没有发现性能发生了巨大变化。我的实现显然没有利用它们是数字的事实。我正在做类似于我们对字符串所做的事情。有没有办法减少搜索空间?我收到的一个提示是建立一个查找表,但我没有得到任何线索。
  • 我认为您永远无法摆脱这样一个事实,即如果您添加新行,则必须搜索所有行,并且搜索将取决于列数。因此,您最终将始终将基于列的搜索时间乘以行数。 (对于无序搜索)

标签: c++ algorithm c++11 search vector


【解决方案1】:

在搜索完全匹配时,您可以通过使用我称之为“移动哈希”的方法来非常高效地完成此操作。

当您搜索时,您会计算搜索字符串的哈希值,同时您会继续计算正在搜索的数据的移动哈希值。在进行比较时,您首先比较哈希,并且只有当匹配时,您才能继续比较实际数据。

现在打勾是选择一种哈希算法,每次移动一个点时都可以轻松更新,而不是重新计算所有内容。这种散列的一个例子是例如。所有数字的总和。

如果我有以下数组:012345678901234567890 并且我想在这个数组中找到 34567,我可以将哈希定义为搜索字符串中所有数字的总和。这将给出25 (3+4+5+6+7) 的哈希值。然后我会搜索数组并不断更新数组上的运行哈希。数组中的第一个哈希是10 (0+1+2+3+4),第二个哈希是15 (1+2+3+4+5)。但是我可以通过添加 5(新数字)和减去 0(旧数字)来更新前一个哈希,而不是重新计算第二个哈希。

由于更新“正在运行的哈希”是 O(1),如果您有一个不会产生很多错误命中的良好哈希算法,那么您可以大大加快该过程。我用作哈希的简单总和太简单了,但其他方法允许更新哈希,例如 XOR ..

【讨论】:

    【解决方案2】:

    如果您想整体上做得更快,但已经有了正确的算法。通过优化代码(内存分配,如果编译器没有删除重复操作等),您可能会获得一些性能。例如,通过删除两个big_matrix[(row * width) + i] 并将其分配给局部变量,可能会有所收获。仔细分析和衡量实际案例。

    为了获得更大的收益,线程可以是一种选择。您可以一次在此处处理一行,因此应该与内核数量大致呈线性加速。 C++ 11 有std::async,它可以处理一些启动线程和获取结果的工作,而不是自己处理std::thread 或平台特定的机制。在较新版本的 C++ 中,还有一些其他较新的东西可能也很有用。

    void searchPatternRow(std::vector<int> const &pattern, std::vector<int> const &big_matrix, int row, int width, std::vector<int> &searchResult);
    void searchPattern(std::vector<int> const &pattern, std::vector<int> const &big_matrix, int begin, int finish, int width, std::vector<int> &searchResult)
    {
        std::vector<std::future<void>> futures;
        for (int row = begin; row < finish; ++row)
            std::async([&, row]() { searchPatternRow(pattern, big_matrix, row, width, searchResult);  });
        for (auto &future : futures) future.wait(); // Note, also implicit when the future from async gets destructed
    }
    

    为了提高线程效率,您可能希望批量搜索 10 行。对于写入searchResult 的同一缓存行的线程也有一些注意事项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      • 2014-08-27
      • 1970-01-01
      • 2011-01-31
      相关资源
      最近更新 更多