my @words = #...; my %triples; foreach (@words) { for (my $i = 0; $i < length($_) - 2; $i++) { push @{$triples{substr $_, $i, 3} ||= []}, $_; } } # Keep most popular triples my @triples = grep { @{$triples{$_}} > 10 } keys %triples; my %lensum; foreach my $t (@triples) { foreach my $w (@{$triples{$t}}) { $lensum{$t} += length $w; } } @triples = sort { $lensum{$b} <=> $lensum{$a} } @triples; my $re = join '|', map quotemeta, @triples; while (<>) { print; my @hopes; while (/$re/gio) { push @hopes, @{$triples{$&}}; } my $word = join '|', map quotemeta, sort { length($b) <=> length($a) } @hopes; 1 while s/$word/[*]/i; print; }