私は修正trieを使用すると思います。
通常は、一つはトライに追加するには、次の使用することができます
sub add {
my $p = \shift;
my $s = shift;
$p = \($$p->{$_}) for split(//, $s);
$$p->{''} = 1;
}
しかし、我々は2つの変更が必要です。文字列を追加するとき
- 文字列のすべての接頭辞を追加する必要があります。たとえば、
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」を追加した場合はどうなりますか?任意の2つの文字列の間で最長の接頭辞を探していますか?または少なくとも1つの共通点を持つ文字列のLCPですか? – Schwern
後者、はい、申し訳ありませんが、明らかでない場合。 – Gambit2007
接頭辞は 'abcd'ですか、' aaa'のように同じ文字を繰り返さなければなりませんか? – toolic