the quick brown fox
brownbrownbrownbrown
..........00000.....
####
xxxyyxxy
yyyxyxxyyyxyxx
....0000...... False match
abcdefga
abcdefgabcdefg
00000000...... False match
####
sub lcssN (\$\$;$) {
my( $ref1, $ref2, $min ) = @_;
my( $swapped, $l1, $l2 ) = ( 0, map length( $$_ ), $ref1, $ref2 );
( $l2, $ref2, $l1, $ref1, $swapped ) = ( $l1, $ref1, $l2, $ref2, 1 ) if $l1 > $l2;
$min = 1 unless defined $min;
my $mask = $$ref1 x ( int( $l2 / $l1 ) + 1 );
my @match = '';
for my $start ( 0 .. $l1-1 ) {
my $masked = substr( $mask, $start, $l2 ) ^ $$ref2;
while( $masked =~ m[\0{$min,}]go ) {
my $l = $+[ 0 ] - $-[ 0 ];
my $match = substr( $$ref2, $-[ 0 ], $l );
next unless 1+index $$ref1, $match;
@match = (
$match,
( $-[ 0 ]+$start ) % $l1,
$-[ 0 ]
) if $l > length $match[ 0 ];
}
}
@match[ 2, 1 ] = @match[ 1, 2 ] if $swapped;
return unless $match[ 0 ];
return wantarray ? @match : $match[ 0 ];
}
####
sub lcssN (\$\$;$) {
my( $ref1, $ref2, $min ) = @_;
my( $swapped, $l1, $l2 ) = ( 0, map length( $$_ ), $ref1, $ref2 );
( $l2, $ref2, $l1, $ref1, $swapped ) = ( $l1, $ref1, $l2, $ref2, 1 ) if $l1 > $l2;
$min = 1 unless defined $min;
my $mask = $$ref1 x ( int( $l2 / $l1 ) );
my @match = '';
for my $start ( 0 .. $l1-1 ) {
my $masked = substr( $mask, $start, $l2 ) ^ $$ref2;
while( $masked =~ m[\0{$min,}]go ) {
my $l = $+[ 0 ] - $-[ 0 ];
my $match = substr( $$ref2, $-[ 0 ], $l );
@match = (
$match,
( $-[ 0 ]+$start ) % $l1,
$-[ 0 ]
) if $l > length $match[ 0 ];
}
}
@match[ 2, 1 ] = @match[ 1, 2 ] if $swapped;
return unless $match[ 0 ];
return wantarray ? @match : $match[ 0 ];
}