#!/usr/bin/perl -w use strict; my $MATCH = 1; my $MISMATCH = -1; my $GAP = -2; sub max { my $i=shift; my $j=shift; if ($i>=$j) { return $i; } else { return $j; } } sub computeAlign { my $s1=shift; my $s2=shift; my @x=split(//, $s1); my @y=split(//, $s2); my $scoremat=shift; my $pointermat=shift; my $m=length($s1)+1; my $n=length($s2)+1; #init scoremat for (my $i=0; $i<$m; $i++) { $scoremat->[$i][0]=$GAP*$i; } for (my $j=0; $j<$n; $j++) { $scoremat->[0][$j]=$GAP*$j; } #init pointermat for (my $i=1; $i<$m; $i++) { $pointermat->[$i][0]=1; } for (my $j=1; $j<$n; $j++) { $pointermat->[0][$j]=3; } #dynamic programming for (my $i=1; $i<$m; $i++) { for (my $j=1; $j<$n; $j++) { my $a=$scoremat->[$i-1][$j]+$GAP; my $b; if ($x[$i-1] eq $y[$j-1]) { $b=$scoremat->[$i-1][$j-1]+$MATCH; } else { $b=$scoremat->[$i-1][$j-1]+$MISMATCH; } my $c=$scoremat->[$i][$j-1]+$GAP; $scoremat->[$i][$j]=max($a, max($b, $c)); if ($scoremat->[$i][$j]==$a) { $pointermat->[$i][$j]=1; } elsif ($scoremat->[$i][$j]==$b) { $pointermat->[$i][$j]=2; } else { $pointermat->[$i][$j]=3; } } } return $scoremat->[$m-1][$n-1]; } sub trackAlign { my $pointermat=shift; my $i=shift; my $j=shift; my $v=shift; if ($i!=0 || $j!=0) { if ($pointermat->[$i][$j]==1) { trackAlign($pointermat, $i-1, $j, $v); push(@$v, 1); } elsif ($pointermat->[$i][$j]==2) { trackAlign($pointermat, $i-1, $j-1, $v); push(@$v, 2); } else { trackAlign($pointermat, $i, $j-1, $v); push(@$v, 3); } } } sub printAlign { my $s1=shift; my $s2=shift; my @x=split(//, $s1); my @y=split(//, $s2); my $v=shift; my $count=0; for (my $i=0; $i<=$#{$v}; $i++) { if ($v->[$i]==3) { print '-'; } else { print $x[$count++]; } } print "\n"; for (my $i=0; $i<=$#{$v}; $i++) { if ($v->[$i]==2) { print '|'; } else { print ' '; } } print "\n"; $count=0; for (my $i=0; $i<=$#{$v}; $i++) { if ($v->[$i]==1) { print '-'; } else { print $y[$count++]; } } print "\n\n"; } if ($#ARGV<1) { print "need two strings to align\n"; exit; } my $s1=$ARGV[0]; my $s2=$ARGV[1]; my $m=length($s1)+1; my $n=length($s2)+1; my @scoremat; my @pointermat; my @v=(); print computeAlign($s1, $s2, \@scoremat, \@pointermat), "\n"; trackAlign(\@pointermat, $m-1, $n-1, \@v); printAlign($s1, $s2, \@v);