在C / C ++中以大文本进行关键字搜索的最快方法

时间:2011-08-16 18:07:02

标签: c++ c performance algorithm search

假设我有100个关键字(可以包含空格),我需要找出它们在一大段文本中出现的次数。快速的方法是什么?

我目前的想法如下:

  • 将关键字转换为后缀树
  • 遍历节点后面的文本,并且每当后缀树中没有出现char(即node-> next == NULL)时,跳到下一个单词并再次搜索

后缀树结构看起来像这样:

struct node {
   int count; //number of occurences (only used at leaf node)
   /* for each lower-case char, have a pointer to either NULL or next node */
   struct node *children[26];
};

我确信有更快的方法可以做到这一点,但它是什么?对于这种情况,空间效率并不是一个大问题(因此子阵列可以更快地查找),但时间效率确实如此。有什么建议吗?

4 个答案:

答案 0 :(得分:4)

后缀树方法的问题是您必须为要搜索的文本的每个字母启动后缀搜索。我认为最好的方法是在文本中安排搜索每个关键字,但使用一些带有预先计算值的快速搜索方法,例如Boyer-Moore

编辑

好的,你可能确定特里可能会更快。 Boyer-Moore的平均情况非常快。例如,考虑字符串的平均长度为m。对于“普通”字符串,BM可以与O(n / m)一样快。这将使100 * O(n / m)。 trie的平均值为O(n * m)(但实际上它可以在现实生活中快得多),所以如果100>>然后特里会赢。

现在有关优化的随机想法。在一些必须进行向后搜索的压缩算法中,我看到了由字符串的两个字符索引的部分哈希表。也就是说,如果要检查的字符串是字符c1c2c3的序列,您可以查看:

if (hash_table[c1 * 256 + c2] == true) check_strings_begining with [c1,c2]

然后是c2c3,依此类推。令人惊讶的是,通过这种简单的检查可以避免多少个案例,因为这个哈希只会每100/65536次(0.1%)为真。

答案 1 :(得分:0)

这就是我要做的。

  1. 将所有关键字放在键值对的哈希表中,关键字的出现次数为值,关键字为(您猜对了)键。
  2. 根据哈希表检查文本blob中的每个单词。如果单词在哈希表中,则增加与其关联的出现次数。
  3. 这是一个好方法,因为哈希表查找是(或应该)分摊O(1)时间。整个算法具有线性复杂性:)。

    编辑:如果您的关键字可以包含空格,则需要制作一种DFA。扫描文件,直到找到您的某个关键“短语”开头的单词。如果第二个(或多个)下一个单词是“关键短语”的一部分,则增加出现次数。

答案 2 :(得分:0)

你好像正在摸索http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm

引用:

算法的复杂性在模式的长度加上搜索文本的长度加上输出匹配的数量是线性的。请注意,因为找到了所有匹配项,所以如果每个子字符串匹配,则可以存在二次匹配数(例如,dictionary = a,aa,aaa,aaaa和输入字符串是aaaa)。

答案 3 :(得分:0)

如果是工业应用,请使用Boost Regex

经过测试,速度很快,很可能会为你节省很多痛苦。