Мне нужно найти самую длинную повторяющуюся строку в подстроке. Допустим, у меня есть строка "bannana"
Википедия говорит следующее:
В информатике проблема самой длинной повторяющейся подстроки — это задача поиска самой длинной подстроки строки, которая встречается не менее двух раз. На рисунке со строкой «ATCGATCGA$» самая длинная повторяющаяся подстрока — «ATCGA».
Итак, я предполагаю, что для строки "bannana"
есть две подстроки одинаковой длины (если не так, поправьте меня): "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$';
для строки "bannana"
он возвращает следующее дерево:
$VAR1 = {
'$' => {},
'n' => {
'a' => {
'na$' => {},
'$' => {}
},
'nana$' => {}
},
'a' => {
'$' => {},
'n' => {
'a$' => {},
'nana$' => {}
}
},
'bannana$' => {}
};
Другая реализация находится в сети здесь, для строки "bannana"
она возвращает следующее дерево:
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"
? - Как видите, деревья разные, эквивалентны они или нет, если да, то почему разные, если нет, то какой алгоритм правильный?
- Если реализация perl неверна, есть ли работающая реализация для perl/python?
- Я читал об алгоритме Укконена, который также упоминается на странице со 2-м примером (я не понял, использует ли онлайн-версия этот алгоритм или нет), использует ли какой-либо из упомянутых примеров этот алгоритм? Если нет, то используется ли алгоритм медленнее или имеет недостатки по сравнению с Укконеном?
bannana
вbanana
. - person n. 1.8e9-where's-my-share m.   schedule 16.07.2015bannana
илиbanana
? Второй выглядит неправильно: у него 5 листьев, ноbannana
имеет 7 букв, поэтому по определению у него должно быть 7 листьев. - person IVlad   schedule 16.07.2015bannana
противbanana
. Этоbannana
@IVlad, если честно, понятия не имею. Моя первоначальная цель - найти самую длинную повторяющуюся подстроку, дерево суффиксов - всего лишь инструмент для этого, как именно они работают, я не знаю. Но что я понял, так это ответ на мою проблему. - person Wakan Tanka   schedule 16.07.2015