检查给定的字符串是否有效地匹配一组前缀

时间:2011-02-27 16:49:49

标签: perl match matching

使用什么算法来检查给定字符串是否与前缀集合中的一个匹配,以及该集合中的哪个前缀?

其他变体:给定路径和一组目录,如何检查路径是否在一组目录中(假设没有符号链接,或者它们无关紧要)?

我对算法的描述或名称感兴趣,或解决此问题的Perl模块(或可用于解决此问题)。

修改
允许有效查找'的解决方案的加分点是字符串集(目录集)之间的关系的前缀

例如,给定一组目录:foo, foo/bar, foo/baz, quux, baz/quux, baz/quux/plugh算法将发现foofoo/barfoo/baz的前缀,而baz/quux是前缀baz/quux/plugh ...希望没有O(n ^ 2)时间。

3 个答案:

答案 0 :(得分:2)

执行此操作的有效方法是使用Trie:

http://en.wikipedia.org/wiki/Trie

CPAN上有一个包:

https://metacpan.org/pod/Tree::Trie

(我自己从未使用过那个包)

您需要考虑哪些操作需要最有效。在Trie中查找非常便宜,但是如果你只为一次查找构建trie,它可能不是最快的方式......

答案 1 :(得分:1)

你提出了一个有趣的问题,但是当我出去寻找这样的事情时(例如List::MoreUtils),我一直回过头来,这与grep有什么不同。所以这就是我基于grep的基本实现。如果你不介意搜索整个列表,或者希望这里的所有匹配都是一个例子:

#!/usr/bin/perl

use strict;
use warnings;

my @prefixes = qw/ pre1 pre2 pre3 /;

my $test = 'pre1fixed';
my @found = grep { $test =~ /^$_/ } @prefixes;

print "$_ is a prefix of $test\n" for @found;

我还想象必须有一些方法可以使用智能匹配运算符~~以短路方式执行此操作。此外,正如工具指出的那样,List::Util函数也可以用于此。这会在找到匹配项后停止搜索。

#!/usr/bin/perl

use strict;
use warnings;

use List::Util qw/first/;

my @prefixes = qw/ pre1 pre2 pre3 /;

my $test = 'pre1fixed';
my $found = first { $test =~ /^$_/ } @prefixes;

print "$found is the prefix of $test\n";

我所知道的唯一算法是Aho-Corasick,但我会将它作为练习留给读者(即我不知道),看看这对你有帮助。我看到有一个模块(Algorithm::AhoCorasick)。我也相信我已经读过某些地方,在某些情况下,这个和trie结构是在Perl的匹配中实现的。也许有人知道我在哪里读到的?编辑:在SO question中找到匹配的替代品

答案 2 :(得分:1)

List::Util核心模块中的first函数可以查找前缀是否与字符串匹配。它搜索前缀列表,并在找到匹配后立即返回。如果没有必要,它不会搜索整个列表:

  

首先返回第一个元素所在的位置   BLOCK的结果是一个真正的值。如果   BLOCK永远不会返回true或LIST   空,然后返回undef。