【问题标题】:Speed problem with SPOJ occurence counting in perlperl 中 SPOJ 出现计数的速度问题
【发布时间】:2011-03-03 00:28:46
【问题描述】:

我在执行与此类似的任务时遇到问题: 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;

现在可以使用了,谢谢:)

【问题讨论】:

  • 数据集有多大,时间限制是多少? :)
  • spoj 测试是秘密的,但我得到了一个示例测试,其中包含 1k 行和每行约 600 个数字。时间限制为1s。我无法检查以上两个在 spoj 上运行了多长时间 :(

标签: perl optimization


【解决方案1】:

一方面,您正在做大量的复制工作。每次您在第一个示例中复制大字符串时,我都会标记:

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 = &lt;&gt;)(或者直接跳过$in,使用$_)。

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

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

不要在前后添加空格,只需使用\b 而不是带有\s 的环视。

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

【讨论】:

  • 谢谢!不幸的是,它仍然太慢;(
猜你喜欢
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多