在字典中查找单词模式,高性能

Finding word patterns in a dictionary, high performance

本文关键字:模式 高性能 单词 查找 字典      更新时间:2023-10-16

我需要建立某种字典,其中还包含每个单词在语言中出现的单词频率。通常,这将使用std::unordereded_map来实现,对吗?现在问题来了。。。我想找到所有符合某些正则表达式的单词及其频率,而性能是我最关心的问题。

我认为我将无法避免在一系列元素上迭代,并按元素检查它们是否匹配模式。因此,我认为使用一对矢量而不是地图可能是明智的:

using namespace std;
typedef vector<pair<string, double>> Dictionary
vector<Dictionary::const_iterator> index;
Dictionary dict;
...
for_each(index['d'], index['e'], DoSomething);

这将使我能够有效地迭代所有以"d"开头的单词。当然,只有当我已经知道正则表达式的第一个字母时,这才有帮助,我想这通常不会是这样。此外,如果我已经知道了整个单词,没有任何不确定性,只想查找它的频率,我就必须遍历整个部分,直到找到它。地图可以让我更快地查找它。例如,在查找单词"deer"时

Dictionary::const_iterator it = 
find_if(index['d'], index['e'], []    // Lambda
(pair<string, double> const &pr)
{
return pr.first == "deer";
});

一点也不优化!一个解决方案可能是针对不同的情况使用不同的字典实现,尽管内存不是什么大问题,但这似乎是一个愚蠢的变通方法。

有什么建议吗?

按照您的想法std::vector<std::pair<boost::regex, int> >可能是效率最高;你反复尝试寻找匹配项。

如果你愿意做这项工作,一个更好的解决方案会实现您自己的正则表达式类,而不需要捕获(大多数正则表达式中的(...)运算符)。在没有捕获的情况下,转换正则表达式相当容易表达式转换为纯DFA,可以正则表达式,每个正则表达式返回不同的接受代码。(这是我自己的正则表达式类作品对于大多数应用程序来说,它的灵活性远不如Boost,因为它不支持捕获。但确实如此允许以下内容:

RegularExpression t1( expr1", 0 );
RegularExpression t2( expr2", 1 );
//  ...
RegularExpression t = t1 | t2 /* | t3 | t4 | ... */ ;

匹配时,如果expr1匹配,它将返回0,如果expr2匹配,则返回1比赛等。;然后,您可以使用匹配id作为索引int的向量。(如果没有匹配,则返回-1。)

通过这种方式,搜索时间相对于输入的长度。不管表达式的数量你正在努力匹配。(我的RegularExpression类设计于20多年前,用于生成编译器前端。大约15年前,我将其重新命名为输入。)

多年来,该代码一直可以在网上找到,但我没有现在有一个网页,所以除非有人保留了一个旧的复制,它不是。我很乐意寄给你,但是警告说图书馆已经有一段时间没有维护了,所以让它用现代的编译器。(它最初是用预标准C++编写的,并且仍然包含许多使其编译的解决方法像Sun CC 4.x这样的东西)

您的最佳选择是使用Finite Satae Transducerhttp://www.ims.uni-stuttgart.de/projekte/gramotron/SOFTWARE/SFST.html。

正如你所说,这张地图会占用很多空间。

您可以将转换器视为一个大型正则表达式(regex是一个编译的自动机)。