我会使用修改trie。
通常情况下,人们可以使用以下方法来添加到特里:
sub add {
my $p = \shift;
my $s = shift;
$p = \($$p->{$_}) for split(//, $s);
$$p->{''} = 1;
}
但我们需要两处修改:
- 字符串的所有前缀必须添加一个字符串时添加。例如,添加
abc
还应该添加a
和ab
到线索。
- 当添加到线索,我们要返回的路径的先前存在的部分的长度。
因此,我们需要:
sub add {
my $p = \shift;
my $s = shift;
my $cp_len = 0;
for (split(//, $s)) {
$p = \($$p->{$_});
++$cp_len if $$p->{$_}{''};
$$p->{''} = 1;
}
return $cp_len;
}
结合(优化版本),这与一个算法来找到一个列表并且用算法最长的字符串从列表中删除重复的字符串来获得下列溶液:
use strict;
use warnings;
use feature qw(say);
sub add {
my $p = \shift;
my $s = shift;
my $cp_len = 0;
for (split(//, $s)) {
++$cp_len if exists($$p->{$_});
$p = \($$p->{$_});
}
return $cp_len;
}
my $t;
my $lcp_len = 0; # lcp = longest common prefix
my %lcps;
while (<>) {
chomp;
my $cp_len = add($t, $_)
or next;
if ($cp_len >= $lcp_len) {
if ($cp_len > $lcp_len) {
$lcp_len = $cp_len;
%lcps =();
}
$lcps{ substr($_, 0, $cp_len) } = 1;
}
}
my @lcps = sort keys %lcps;
if (@lcps) {
say "Longest common prefix(es): @lcps";
} else {
say "No common prefix";
}
数据:
abc
abc
abcd
abcde
hijklx
hijkly
mnopqx
mnopqy
输出:
Longest common prefix(es): hijkl mnopq
由上述所花费的时间正比于输入字符的数目。
会发生什么,如果“j12345”是组合?如果我们添加“bbbb1”和“bbbb2”会怎么样?它是否正在寻找任何两个字符串之间最长的前缀?还是至少有一个共同点的字符串是LCP? – Schwern
后者,是的,如果不明确,很抱歉。 – Gambit2007
前缀是否可以是'abcd',还是必须是重复的相同字母,比如'aaa'? – toolic