Эффективное сопоставление подстрок в perl
Я ищу эффективное решение, чтобы найти максимальную подстроку в строке терпеть n несоответствия в главной строке
например: Главный Строка
- AGACGTACTACTCTACTAGATGCA * TACTCTAC*
- AGACGTACTACTCTACTAGATGCA * TACTCTAC*
- AGACGTACTACTCTACAAGATGCA * TACTCTAC*
- AGACGTACTACTTTACAAGATGCA * TACTCTAC*
Поиск Строку:
- TACTCTACT: это следует считать совпадением со всеми вышеперечисленными основными строками.
также я там мог быть случай где часть подстроки находится в конце основной строки, и я хотел бы также ее подобрать.
Я был бы признателен, если бы вы могли дать несколько советов.
PS: у меня будет одна строка поиска и около 100 миллионов основных строк для поиска подстроки.
спасибо! - Абхи!--3-->
2 ответов
use strict;
use warnings;
use feature qw( say );
sub match {
my ($s, $t, $max_x) = @_;
my $m = my @s = unpack('(a)*', $s);
my $n = my @t = unpack('(a)*', $t);
my @length_at_k = ( 0 ) x ($m+$n);
my @mismatches_at_k = ( 0 ) x ($m+$n);
my $offset = $m;
my $best_length = 0;
my @solutions;
for my $i (0..$m-1) {
--$offset;
for my $j (0..$n-1) {
my $k = $j + $offset;
if ($s[$i] eq $t[$j]) {
++$length_at_k[$k];
}
elsif ($length_at_k[$k] > 0 && $mismatches_at_k[$k] < $max_x) {
++$length_at_k[$k];
++$mismatches_at_k[$k];
}
else {
$length_at_k[$k] = 0;
$mismatches_at_k[$k] = 0;
}
my $length = $length_at_k[$k] + $max_x - $mismatches_at_k[$k];
$length = $i+1 if $length > $i+1;
if ($length >= $best_length) {
if ($length > $best_length) {
$best_length = $length;
@solutions = ();
}
push @solutions, $i-$length+1;
}
}
}
return map { substr($s, $_, $best_length) } @solutions;
}
say for match('AABBCC', 'DDBBEE', 2);
выход:
AABB
ABBC
BBCC
Я не уверен, что это то, что вам нужно, но BioPerl имеет приблизительный инструмент grep под названием Bio::Grep::Backend::Agrep
:
Bio::Grep::Backend:: Agrep ищет запрос с agrep
и agrep
является "приблизительным grep". AFAIK, это создает базу данных, а затем использует эту базу данных, чтобы сделать ваши поиски быстрее, так что это звучит как то, что вы после.
Похоже, вы работаете с последовательностями ДНК, поэтому вы вероятно, BioPerl уже установлен.
вы также можете попробовать использовать String::Approx
напрямую:
расширение Perl для приблизительного соответствия (нечеткое соответствие)
Я подозреваю, что Bio::Grep::Backend::Agrep
будет быстрее и лучше соответствовать вашей задаче.