我将在这里解释这个问题。
假设我有1000个单词的列表。说它是字典。如果单词正确或者给出最接近的匹配,用户将输入一些单词并匹配完全匹配。就像谷歌搜索一样,我们输入的内容就是最接近的匹配。
我认为是
的算法Read the word list one by one
split our input word string into characters
take the first word from the list and match character wise
similarly do it for other words in the list
我知道这是漫长的道路,需要很多时间。有谁知道如何实现更好的算法
答案 0 :(得分:5)
使用/usr/share/dict/words
执行快速而肮脏的操作(您仍需要执行levensthein距离部分和选择)
免责声明:借用http://www.perlmonks.org/?node_id=503154
的二进制搜索代码open(FILE, "<", "/usr/share/dict/words");
my @lines = <FILE>;
my $word = $ARGV[0];
sub BinSearch
{
my ($target, $cmp) = @_;
my @array = @{$_[2]};
my $posmin = 0;
my $posmax = $#array;
return -0.5 if &$cmp (0, \@array, $target) > 0;
return $#array + 0.5 if &$cmp ($#array, \@array, $target) < 0;
while (1)
{
my $mid = int (($posmin + $posmax) / 2);
my $result = &$cmp ($mid, \@array, $target);
if ($result < 0)
{
$posmin = $posmax, next if $mid == $posmin && $posmax != $posmin;
if ($mid == $posmin){
return "Not found, TODO find close match\n";
}
$posmin = $mid;
}
elsif ($result > 0)
{
$posmax = $posmin, next if $mid == $posmax && $posmax != $posmin;
if ($mid == $posmax){
return "Not found, TODO find close match\n";
}
$posmax = $mid;
}
else
{
return "Found: ".@array[$mid];
}
}
}
sub cmpFunc
{
my ($index, $arrayRef, $target) = @_;
my $item = $$arrayRef[$index];
$item =lc($item);
$target =lc($target);
$a = $item cmp $target;
return $a;
}
print BinSearch($word."\n", \&cmpFunc, \@lines)."\n";
用法(如果脚本名为find_words.pl
):
perl find_words.pl word
单词是您要搜索的单词。
答案 1 :(得分:4)
这种“模糊”单词搜索的常用算法是Levenshtein distance。它并没有真正找到类似的单词,但计算单词的相似性。然后,排序或过滤函数可以使用此相似性得分(或Levenshtein距离)来选择相似的单词。
如何测量距离很简单:需要将多少个字符从目标字词更改为匹配的字词。例如,距离为3表示单词之间的差异为3次编辑(不一定是字符,因为它还包括添加和删除字符的行为)。
Rosetta Code网站列出了以各种语言实现的Levenshtein距离算法,包括tcl和perl:http://rosettacode.org/wiki/Levenshtein_distance
tcler维基上有一个页面讨论了相似度算法,其中包括Levenshtein距离的几种实现:similarity
对于perl,还有一个可以使用的CPAN模块:Text::Levenshtein
所以在perl中你可以做到:
use Text::Levenshtein;
my %word_distance;
@word_distance{@dictionary} = distance($word,@dictionary);
然后遍历word_distance
哈希以找到最相似的单词。
答案 2 :(得分:2)
使用简单的二进制搜索获得相似单词的邻域然后使用Levenshtein算法进行细化的问题是错误可能发生在单词的早期以及后期;如果出现早期错误,您将面临完全遗漏单词的风险。更有效的技术可能是使用Soundex算法在单词列表中创建排序键,以便您按基本相似性进行搜索。然后你可以使用Levenshtein来改进,但是通过基础源语料库中的词语的稀有性来加权这种相似性度量;假设用户更可能想要一个普通单词而不是一个罕见的单词是一个有用的措施。 (这假设你有一个源语料库,但是如果你想模仿谷歌那么你肯定有其中一个。)
最好是考虑使用某种map-reduce机制在整个单词集上运行加权Levenshtein距离度量的方法。这更像是“解决问题的硬件”方法,但避免了由于初始过滤器导致错过单词的潜在问题所带来的问题。唉,这确实意味着你最终会得到一些无法作为一个简单软件的一部分推送的东西(支持这样的东西的配置系统不太可能是你想要强加的东西)普通用户)但在服务后部署可能是切实可行的。