0

我有一个非常大的数据集(范围从 100,000 个元素到 250,000 个元素),我目前将数据存储在一个向量中,目的是搜索一组单词。给定一个短语(例如“on, para”),该函数应该找到以给定短语开头的所有单词并将所有匹配项推送到队列中。

为了找到第一个单词,我使用了似乎效果很好的二进制搜索,但是在找到第一个单词之后我就卡住了。我应该如何在元素之前和之后有效地迭代以找到所有相似的单词?输入是按字母顺序排列的,所以我知道所有其他可能的匹配都将在元素返回之前或之后发生。我觉得其中一定有一个<algorithm>我可以利用的功能。以下是相关代码的一部分:

二分查找功能:

int search(std::vector<std::string>& dict, std::string in)
{
    //for each element in the input vector
    //find all possible word matches and push onto the queue
    int first=0, last= dict.size() -1;
    while(first <= last)
    {
        int middle = (first+last)/2;
        std::string sub = (dict.at(middle)).substr(0,in.length());
        int comp = in.compare(sub);
        //if comp returns 0(found word matching case)
        if(comp == 0) {
            return middle;
        }
        //if not, take top half
        else if (comp > 0)
            first = middle + 1;
        //else go with the lower half
        else
            last = middle - 1;
    }
    //word not found... return failure
    return -1;
}

main()

//for each element in our "find word" vector
for (int i = 0; i < input.size()-1; i++)
{
    // currently just finds initial word and displays
    int key = search(dictionary, input.at(i));
    std::cout << "search found " << dictionary.at(key) <<
                 "at key location " << key << std::endl;
}
4

3 回答 3

1

std::lower_bound 并向前迭代(您也可以使用 std::upper_bound):

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    typedef std::vector<std::string> Dictionary;
    Dictionary dictionary = {
        "A", "AA", "B", "BB", "C", "CC"
    };
    std::string prefix("B");
    Dictionary::const_iterator pos = std::lower_bound(
        dictionary.begin(),
        dictionary.end(),
        prefix);
    for( ; pos != dictionary.end(); ++pos) {
        if(pos->compare(0, prefix.size(), prefix) == 0) {
            std::cout << "Match: " << *pos << std::endl;
        }
        else break;
    }
    return 0;
}
于 2013-10-07T17:29:25.223 回答
0

您不需要为每个短语建立索引,而是为任何子短语建立索引。从单词开始。例如,对于 dict-string "New York",您必须为两个字符串保留索引:"New York" 和 "York"。请参阅我的自动完成演示,它说明了这个想法:

http://olegh.cc.st/autocomplete.html

如您所见,这个子系统可以快速处理字典,比您的 250K 元素还大。当然,我不使用那里的二进制搜索,因为它很慢。我使用散列代替。

于 2013-10-07T17:14:08.103 回答
0

有序向量(列表)当然是存储数据的一种方式,但保持项目有序会带来效率成本。而且你没有提到你的数组是静态的还是动态的。但是还有其他数据结构允许存储已排序的数据并具有非常好的查找​​时间。

  • 哈希/映射 - 您可以将您的项目存储为哈希/映射并进行非常快速的查找,但查找下一个和上一个是有问题的。
  • 二叉树/N-ary Tree/B-Tree - 非常好的动态插入/删除性能,以及良好的查找时间,并且树是有序的,所以 find next/previous 是稳定的。
  • 布隆过滤器 - 有时您要做的就是检查一个项目是否在您的收藏中,布隆过滤器的误报率非常低,因此它是一个不错的选择。

假设您将数据分解为短子序列(音节),那么您可以拥有一个音节树,非常快速的查找,并且根据树是实现为有序列表还是哈希/映射,您可能还能够找到下一个/上一个。

于 2013-10-07T20:36:39.333 回答