【发布时间】:2010-11-09 03:45:31
【问题描述】:
我有大量的单词(大约 10,000 个),我需要找出其中是否有任何单词出现在给定的文本块中。
有没有比对文本块中的每个单词进行简单文本搜索更快的算法?
【问题讨论】:
我有大量的单词(大约 10,000 个),我需要找出其中是否有任何单词出现在给定的文本块中。
有没有比对文本块中的每个单词进行简单文本搜索更快的算法?
【问题讨论】:
将 10,000 个单词输入到哈希表中,然后检查文本块中的每个单词是否有条目。
虽然我不知道更快,但只是另一种方法(取决于您要搜索的字数)。
简单的 perl 示例:
my $word_block = "the guy went afk after being popped by a brownrabbit";
my %hash = ();
my @words = split /\s/, $word_block;
while(<DATA>) { chomp; $hash{$_} = 1; }
foreach $word (@words)
{
print "found word: $word\n" if exists $hash{$word};
}
__DATA__
afk
lol
brownrabbit
popped
garbage
trash
sitdown
【讨论】:
试试 Aho-Corasick 算法: http://en.wikipedia.org/wiki/Aho-Corasick_algorithm
【讨论】:
建立一个trie 你的单词,然后用它来查找文本中的哪些单词。
【讨论】:
答案很大程度上取决于实际需求。
假设文本块与单词列表相比相对较小并且每个文本块只处理一次,我建议将单词列表中的单词放入哈希表中。然后您可以对文本块中的每个单词执行哈希查找,并找出单词列表中是否包含该单词。
如果您必须多次处理文本块,我建议反转文本块。反转文本块意味着为每个单词创建一个列表,其中包含包含特定单词的所有文本块。
在其他情况下,为每个文本块生成一个位向量可能会有所帮助,每个单词一个位指示该单词是否包含在文本块中。
【讨论】:
您可以构建一个用作状态机的图形,当您处理输入单词的第 i 个字符 - Ci - 您尝试通过检查您的前一个节点是否链接到 Ci-1 来进入图形的第 i 个级别, 有一个子节点链接到 Ci
例如:如果您的语料库中有以下单词
(“艺术”、“是”、“是”、“蜜蜂”)
您的图中将有以下节点
n11 = 'a'
n21 = 'r'
n11.sons = (n21)
n31 = 'e'
n32='t'
n21.sons = (n31, n32)
n41='art' (这里我们的图中有一个叶子,并且所有上层节点的单词 build 都与这个节点相关联)
n31.sons = (n41)
n42 = 'are' (这里又是一个词)
n32.sons = (n42)
n12 = 'b'
n22 = 'e'
n12.sons = (n22)
n33 = 'e'
n34 = '是' (单词)
n22.sons = (n33,n34)
n43 = '蜜蜂' (单词)
n33.sons = (n43)
在处理过程中,如果您在处理输入单词的最后一个字符时穿过一片叶子,并且仅在这种情况下,这意味着您的输入在您的语料库中。
这种方法比单个 Dictionary 或 Hashtable 实现起来更复杂,但在内存使用方面会更加优化
【讨论】:
Boyer-Moore string algorithm 应该可以工作。根据文本块中的大小/# 或单词,您可能希望将其用作搜索单词列表的关键字(列表中的单词是否比块中的单词多)。另外 - 您可能想从两个列表中删除任何重复。
【讨论】: