Rather than inserting the brackets as the substrings are found, you could keep track of the indicies of the substrings, filter out interior indicies for overlapping substrings, then insert the brackets at the remaining indicies.
Lessee... somthing like...
#!/usr/bin/perl -w
use strict;
my $s1 ='CCCATCTGTCCTTATTTGCTG'; my @a1 = qw(ATCTG ATTTG);
my $s2 ='ACCCATCTGTCCTTGGCCAT'; my @a2 = qw(CCATC);
my $s3 ='CCACCAGCACCTGTC'; my @a3 = qw(CCACC CCAGC GCACC);
my $s4 ='CCCAACACCTGCTGCCT'; my @a4 = qw(CCAAC ACACC);
put_bracket($s1,\@a1);
put_bracket($s2,\@a2);
put_bracket($s3,\@a3);
put_bracket($s4,\@a4);
sub put_bracket
{
my ($str,$ar) = @_;
my $slen = length $ar->[0];
my @brackets;
foreach my $subs ( @$ar )
{
my $idx = index($str,$subs);
my $bgn = $idx;
my $end = $idx + $slen + 1;
push @brackets, ($bgn, $end);
}
my @filtered = $brackets[0];
for (1..$#brackets-1)
{
push @filtered, $brackets[$_] if
($brackets[$_] < $brackets[$_+1] and
$brackets[$_-1] < $brackets[$_]);
}
push @filtered, $brackets[-1];
while (@filtered)
{
substr($str, pop @filtered, 0, ']');
substr($str, pop @filtered, 0, '[');
}
print $str,"\n";
return;
}
Edit: Note that the above could return some incorrect brackets if all of the substrings are not the same length. It is probably moot though, as I see you assume that all of the substrings are the same length in your original example