使用什么算法来检查给定字符串是否与前缀集合中的一个匹配,以及该集合中的哪个前缀?
其他变体:给定路径和一组目录,如何检查路径是否在一组目录中(假设没有符号链接,或者它们无关紧要)?
我对算法的描述或名称感兴趣,或解决此问题的Perl模块(或可用于解决此问题)。
修改
允许有效查找'的解决方案的加分点是字符串集(目录集)之间的关系的前缀
例如,给定一组目录:foo, foo/bar, foo/baz, quux, baz/quux, baz/quux/plugh
算法将发现foo
是foo/bar
和foo/baz
的前缀,而baz/quux
是前缀baz/quux/plugh
...希望没有O(n ^ 2)时间。
答案 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。