- 论坛徽章:
- 0
|
我这个算法,用的是一个比较老套的lcs算法。以前用c写过,在perl下又模仿实现了一下。
算法大概描述就是,分别用两个字符串作为横坐标和纵坐标建一个矩阵,遇到横竖字符相同的时候把这点的值设成1,否则设成零,最后矩阵中最长的不为零的对角线就是最大子字串。
例如:
| m | a | c | h | i | a | 0 | 1 | 0 | 0 | 0 | b | 0 | 0 | 0 | 0 | 0 | m | 1 | 0 | 0 | 0 | 0 | a | 0 | 1 | 0 | 0 | 0 | c | 0 | 0 | 1 | 0 | 0 |
这样有点问题:建完矩阵还要去找最长对角线,麻烦。
解决方案是:相等时不只把矩阵元素设为“1”,而是设成它左上角的元素值加一。
例如:
| m | a | c | h | i | a | 0 | 1 | 0 | 0 | 0 | b | 0 | 0 | 0 | 0 | 0 | m | 1 | 0 | 0 | 0 | 0 | a | 0 | 2 | 0 | 0 | 0 | c | 0 | 0 | 3 | 0 | 0 |
所以矩阵建好后,找到矩阵中最大的元素就ok了。
上面的那个多少还有点像用perl写的c程序,下面给个更像perl程序的:
#!perl
sub max_mutual_str {
my($str1,$str2) = @_;
my %cmp;
my $max;
my @list1=split '',$str1;
my @list2=split '',$str2;
for my $i (0..$#list1){
for my $j (0..$#list2){
$cmp{$i.$j}=($list1[$i] eq $list2[$j]) ? (1+$cmp{($i-1).($j-1)}) : 0;
$max=$cmp{$i.$j} if ($cmp{$i.$j}>$max);
print "$cmp{$i.$j}";
}
print "\n";
}
for (keys %cmp){
if ($cmp{$_} == $max ){
my $offset=substr($_,0,1)+1-$max;
return substr($str1,$offset,$max);
}
}
}
my ($str1,$str2) = @ARGV;
my $str= max_mutual_str($str1,$str2);
print "$str\n"; |
|
|