私は30倍以上速い方法を見つけましたが、間違いなくその不正行為です。 Benchmark.pmのコードをベンチマークに含めました。あなたはそれに慣れていないようです。
ベンチマークは以下のとおりです。
Rate Join Cheat
Join 83294/s -- -97%
Cheat 2580687/s 2998% --
とコード。三行目の後、私はそのは間違いなく浮気理由を理解すると思う:もちろん
use v5.14;
use Benchmark qw(cmpthese);
use Inline 'C';
sub an_join {
my ($s1, $s2) = @_;
return (join '', sort split(//, $s1)) eq
(join '', sort split(//, $s2));
}
use constant {
STR1 => 'abcdefghijklm',
STR2 => 'abcdefghijkmm',
STR3 => 'abcdefghijkml',
};
cmpthese(
0,
{
'Join' => 'an_join(STR1, STR2); an_join(STR1, STR3)',
'Cheat' => 'an_cheat(STR1, STR2); an_cheat(STR1, STR3)',
});
__END__
__C__
int an_cheat(const char *a, const char *b) {
unsigned char vec_a[26], vec_b[26];
const char *p, *end;
memset(vec_a, 0, sizeof(vec_a));
memset(vec_b, 0, sizeof(vec_b));
end = a+strlen(a);
for (p = a; p < end; ++p)
if (*p >= 'a' && *p <= 'z')
++vec_a[(*p)-'a'];
end = b+strlen(b);
for (p = b; p < end; ++p)
if (*p >= 'a' && *p <= 'z')
++vec_b[(*p)-'a'];
return 0 == memcmp(vec_a, vec_b, sizeof(vec_a));
}
、その不正行為そのものPerl-そのC.中で書かれていないので、それはPerlのバージョンにはない制限があります(大文字の小文字のASCII文字でのみ動作し、他のすべての文字は無視されます)。しかし、本当にスピードが必要な場合は、このような不正行為を使用することができます。
編集:
は(本当に、よく、生の8ビット文字)のLatin1のすべてに拡張します。また、コンパイラが単純なループ(ポイント演算なし)を最適化し、読みやすくすることができたことがわかりました。ベンチマークでは、小文字のASCIIのみのバージョンは約10%高速です:
int an_cheat_l1b(const char *a, const char *b) {
unsigned char vec_a[UCHAR_MAX], vec_b[UCHAR_MAX];
size_t len, i;
memset(vec_a, 0, sizeof(vec_a));
memset(vec_b, 0, sizeof(vec_b));
len = strlen(a);
for (i = 0; i < len; ++i)
++vec_a[((const unsigned char *)(a))[i]];
len = strlen(b);
for (i = 0; i < len; ++i)
++vec_b[((const unsigned char *)(b))[i]];
return 0 == memcmp(vec_a, vec_b, sizeof(vec_a));
}
Cバージョンの利点は、PerlバージョンO(n・logn)とは対照的に、Θ(n)以降の文字列が長くなるにつれて長くなることに注意してください。また、完全なLatin1のペナルティは減少します。ペナルティはおそらくmemcmpです。
アレイ比較のための興味深い読み取り:http://stackoverflow.com/questions/1609467/in-perl-is-there-a-built-in-way-to-compare-two-arrays-for-equality – Mat
また、文字列の長さが異なる場合は、文字列の長さを比較してfalseを返すこともできます。これは、あくまでもアナグラムでない文字列を並べ替えることを避けるためです。同じ長さの文字列の場合、長さの比較は非常に迅速で、split-sort-joinよりもはるかに速いため、パフォーマンスの低下はごくわずかです。 –
さて、あなたはそれを必要としません: 'join ''、sort split(//、$ s1)'という比較関数を取り除くことで、パフォーマンスを向上させることができます。 – derobert