Perl中SPOJ发生计数的速度问题

时间:2011-03-03 00:28:47

标签: perl optimization

我遇到与此类似的任务有问题: click (translated)(我被指派的那个有更大的测试和更短的时间限制)。快速翻译任务:

编写一个程序,检查给定序列中给定数字的出现次数。

输入:给定数字,序列中有多少个数字,数字序列

输出:出现次数

到目前为止我的解决方案:

1

#!/usr/bin/env perl

while (<>) {
    $in = $_;
    @nums = split / /, $in, 3;

    $what = shift @nums;
    shift @nums;
    $rest = shift @nums;
    $rest = " ".$rest." ";

    $sum = () = $rest =~ /(?<=\s)$what(?=\s)/g;

    print $sum;
    print "\n";
}

2

#!/usr/bin/env perl

while (<>) {
    $in = $_;
    @nums = split / /, $in, 3;

    $what = shift @nums;
    shift @nums;
    $rest = shift @nums;
    $rest = " ".$rest." ";

    if(!$reg{$what}){
        $reg{$what} = qr/(?<=\s)$what(?=\s)/;
    }
    $sum = () = $rest =~ /$reg{$what}/g;

    print $sum;
    print "\n";
}

我也尝试过暴力方法,哈希表,grep ...所有超出给定的时间限制,我不知道如何编写任何比上面两个更快的工作。有什么想法吗?

编辑:摆脱复制列表后(原来数字也可以是负数):

#!/usr/bin/env perl

while ($line = <>) {
        $line =~ s/^(-?\d+) \d+//;
        $what = $1;

        $sum = () = $line =~ / $what\b/g;

    print $sum;
    print "\n";
}

edit2 :通过http://www.chengfu.net/2005/10/count-occurrences-perl/

print $sum = (($line =~ s/ $1\b//g)+0);

导致代码比以下快2倍:

print $sum = () = $line =~ / $1\b/g;

立即行动,谢谢:)

1 个答案:

答案 0 :(得分:3)

首先,你正在进行大量的复制。我在第一个例子中每次复制一个大字符串时都标记了:

while (<>) {
    $in = $_;                   # COPY
    @nums = split / /, $in, 3;  # COPY

    $what = shift @nums;
    shift @nums;
    $rest = shift @nums;        # COPY
    $rest = " ".$rest." ";      # COPY

    $sum = () = $rest =~ /(?<=\s)$what(?=\s)/g;

    print $sum;
    print "\n";
}

为了加快速度,请避免使用副本。例如,使用while ($in = <>)(或只是跳过$in并使用$_)。

为了提取$what和计数,我想我会尝试这而不是split

$in =~ s/^(\d+) \d+//;
$what = $1;

不要在前后添加空格,只需使用\b代替\s的外观。

    $sum = () = $in =~ /\b$what\b/g;