比较短字符串和小字典(解析)的最有效方法

时间:2012-07-09 17:13:21

标签: c algorithm parsing lexical-analysis

我正在尝试优化我为了好玩而制作的简单C解释器,我正在进行这样的解析 - 首先我将文件解析为双向链表中的标记,然后我进行语法和语义分析。
我想用这个原型优化功能:

bool parsed_keyword(struct token *,char dictionary [] []);

在函数内部,我基本上会对所有关键字调用strcmp并编辑令牌类型。 这当然导致对每个被解析的字符串(几乎)进行20次strcmp调用。

我当时认为Rabin-Karp会是最好的,但听起来我觉得它不适合这项工作(将一个词与小词典相匹配)。 做这项工作的最佳算法是什么?感谢您的任何建议。

5 个答案:

答案 0 :(得分:3)

哈希表可能是我对这个特定问题的选择。它将为您的大小的表提供O(1)查找。虽然特里也是个不错的选择。

但是,最简单的实现方法是按字母顺序将单词放在数组中,然后使用C库中的bsearch。它应该与hash或trie一样快,因为你只处理30个单词。它实际上可能比哈希表更快,因为您不必计算哈希值。

Steve Jessop的想法是一个很好的想法,在相同大小的char数组中端到端地布局你的字符串。

const char keywords[][MAX_KEYWORD_LEN+1] = {
 "auto", "break", "case", /* ... */, "while"
};

#define NUM_KEYWORDS sizeof(keywords)/sizeof(keywords[0])

int keyword_cmp (const void *a, const void *b) {
    return strcmp(a, b);
}

const char *kw = bsearch(word, keywords, NUM_KEYWORDS, sizeof(keywords[0]),
                         keyword_cmp);

int kw_index = (kw ? (const char (*)[MAX_KEYWORD_LEN+1])kw - keywords : -1);

如果您还没有,则应考虑获取Compilers: Principles, Techniques, and Tools的副本。由于它的封面,它通常被称为 The Dragon Book

答案 1 :(得分:1)

如果您正在寻找效率,我会说Rabin Karp不是您最好的选择,而且您可以在Boyer-Moore中找到最佳效率,但实施起来要困难得多。

如果你这样做是为了好玩,说实话,我认为没有必要进行优化,因为这些调用仍然应该在相当短的时间内运行,而你并不需要它以行业速度运行。

如果您希望使用字符串匹配算法,这是一个很酷且有用的目标,我建议您查看KMP算法和Boyer-Moore算法,这两种方法在实施过程中都会教会您很多。

当然还有其他更直接的方法,比如字典查找和简单的二进制搜索等......但是那些并没有真正优化你正在处理字符串和字符串比较的事实是一个非常有趣的领域,你将不可避免地陷入某种程度。

答案 2 :(得分:1)

假设您的关键字没有变化,这听起来像perfect hash function的正确情况。完美的哈希函数将输入映射到整数(如常规哈希函数),但没有冲突。

Wikipedia包含几个完美哈希生成器的链接,包括GNU gperf

答案 3 :(得分:0)

进行查找时首先想到的是只使用排序的键盘数组,然后对它们进行二进制搜索。

答案 4 :(得分:0)

如果关键字集是固定的,您可以使用完美散列,例如使用gperf。这只需要不断的工作和单个字符串比较,因此可能比其他方法更快。