在2d向量中搜索数字序列的更快方法是什么?

时间:2018-10-08 10:27:55

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

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

假定文件中的2d数组被读入一个1d大向量中,并以big_matrix(row * x + width)的形式访问。 我想在同一2D数组上进行3种搜索。它们是搜索排序,无序搜索,最佳匹配。这是我使用每种搜索功能的方法。

搜索顺序:此函数查找存在给定数字序列(数字顺序很重要)的所有行。这是找到我实现的给定数字序列的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))?

2 个答案:

答案 0 :(得分: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的同一缓存行的线程,还有一些注意事项。

答案 1 :(得分: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),因此,如果您有一个不错的Hash算法,并且不会产生很多错误命中,则可以大大加快该过程。我用作哈希的简单总和可能太简单了,但是其他方法允许这种哈希更新,例如 XOR ..