我需要在子字符串中找到最长的重复字符串。我们说我有字符串"bannana"
维基百科says以下:
在计算机科学中,最长的重复子串问题是 找到发生在的字符串的最长子串的问题 至少两次。在图中带字符串" ATCGATCGA $",最长 重复的子串是" ATCGA"
所以我假设对于字符串"an"
,有两个同样长的子字符串(如果不正确我请):"na"
和use strict;
use warnings;
use Data::Dumper;
sub classify {
my ($f, $h) = (shift, {});
for (@_) { push @{$h->{$f->($_)}}, $_ }
return $h;
}
sub suffixes {
my $str = shift;
map { substr $str, $_ } 0 .. length($str) - 1;
}
sub suffix_tree {
return +{} if @_ == 0;
return +{ $_[0] => +{} } if @_ == 1;
my $h = {};
my $classif = classify sub { substr shift, 0, 1 }, @_;
for my $key (sort keys %$classif) {
my $subtree = suffix_tree(
grep "$_", map { substr $_, 1 } @{$classif->{$key}}
);
my @subkeys = keys %$subtree;
if (@subkeys == 1) {
my $subkey = shift @subkeys;
$h->{"$key$subkey"} = $subtree->{$subkey};
} else { $h->{$key} = $subtree }
}
return $h;
}
print +Dumper suffix_tree suffixes 'bannana$';
。
维基百科也says为此目的使用后缀树。更具体的here是引用怎么做(这似乎比wikipedia上的定义更明白):
构建一个后缀树,然后找到至少为2的最高节点 后代。
我发现了几种后缀树的实现。以下代码取自here:
"bannana"
对于字符串$VAR1 = {
'$' => {},
'n' => {
'a' => {
'na$' => {},
'$' => {}
},
'nana$' => {}
},
'a' => {
'$' => {},
'n' => {
'a$' => {},
'nana$' => {}
}
},
'bannana$' => {}
};
,它返回以下树:
"bannana"
另一个实现是here在线,对于字符串 7: a
5: ana
2: annana
1: bannana
6: na
4: nana
3: nnana
|(1:bannana)|leaf
tree:|
| |(4:nana)|leaf
|(2:an)|
| |(7:a)|leaf
|
| |(4:nana)|leaf
|(3:n)|
| |(5:ana)|leaf
3 branching nodes
,它返回以下树:
"an"
问题:
"na"
和getdate() + 5
字符串?答案 0 :(得分:1)
1。我如何从这些图表中获得""和" na"字符串?
构建一个后缀树,然后找到至少有2个后代的最高节点。
string-node
是从根到此节点的每个节点的连接字符串。 highest node
是最大长度为string-node
的节点。
在第二个问题的答案中查看树。 (3:n)
有2个后代,节点的路径为(2:a)->(3:n)
,连接为an
。同样适用于(5:a)
获取na
。
2。你可以看到树是不同的,它们是否相同,如果是,为什么它们是不同的,如果不是哪种算法是正确的?
这些树是不同的。为字符串"bannana$"
重建第二个树(
和第一棵树一样):
8: $
7: a$
5: ana$
2: annana$
1: bannana$
6: na$
4: nana$
3: nnana$
|(1:bannana$)|leaf
tree:|
| | |(4:nana$)|leaf
| |(3:n)|
| | |(7:a$)|leaf
|(2:a)|
| |(8:$)|leaf
|
| |(4:nana$)|leaf
|(3:n)|
| | |(6:na$)|leaf
| |(5:a)|
| | |(8:$)|leaf
|
|(8:$)|leaf
5 branching nodes
3。如果perl实现错误,是否有任何perl / python的工作实现?
我不了解Perl,但树构建正确。
4。我已经读过Ukkonen的算法,这个算法也在第二个例子的页面上提到过(如果在线版本是否使用这个算法,我没有抓到),是否有任何一个提到的例子使用这个算法?如果没有,与Ukkonen相比,算法运算速度较慢或有任何缺点吗?
我之前说过,我不知道Perl,但它在第一个algorthim中的意思是它至少有效O(n^2)
(n
它是长度字符串):< / p>
map { substr $str, $_ } 0 .. length($str) - 1;
Ukkonen算法的线性时间为O(n)
。
第一种算法也是递归的,可能会影响已用内存。