压缩束(字符串对)

时间:2016-01-11 13:33:35

标签: python algorithm perl

我有一堆串成串的字符串 例如,这些是三对。第一个有两个字符串" a"," 1"

a,1
a,2
b,1

在我的项目中,我需要压缩这些数据。 对于上述数据,压缩数据是。 (压缩到未压缩的是笛卡尔积)

{a} <=> {1,2}
{b} <=> {1}

提出最佳压缩数据的最佳算法是什么。这里最优的是映射数量较少 我可以写一个简单的脚本,用第一个字符串创建一个哈希表。即使它在某些情况下(大多数情况下)提供了最佳压缩数据,但它并不总是如此。 例如,

a,1
a,2
b,1
c,2

使用第一个字符串作为键的哈希表会给我下面的压缩数据

{a} <=> {1,2}
{b} <=> {1}
{c} <=> {2}

但那不是最佳压缩数据。如果我使用第二个字符串

,我将低于压缩
{a,b} <=> {1}
{a,c} <=> {2}

压缩数据的最佳算法是什么?

2 个答案:

答案 0 :(得分:1)

这个问题相当于用最小行数覆盖二进制矩阵的1或0。

例如,考虑以下示例:a1,b1,b2,c1,c2,d2,d3,d4,e3,e4,e5。这可以放在矩阵中,如下所示:

  1 2 3 4 5
a 1
b 1 1
c 1 1
d   1 1 1
e     1 1 1

最小的解决方案是越过d和e行给出:

d : {2, 3, 4}
e : {3, 4, 5}

以及第1列和第2列

1 : {a, b, c}
2 : {b, c, d}

以便在压缩映射中达到最小数量的条目。

此问题的解决方案在Hungarian Algorithm: How to cover 0 elements with minimum lines?

中的stackoverflow上的其他位置处理

答案 1 :(得分:0)

这绝对不是速度优化的,但这个问题确实引起了我的注意。我对输入格式并不是很确定,但改变这一点应该是微不足道的。这是我的想法,基本上我认为你需要一个两遍,因为在你到达数据末尾之前你无法知道哪种压缩是最好的:

use strict;
use warnings;

use Data::Dumper;

sub compress_strings {
    my @strings = @_;
    my %keys_hash;
    my %values_hash;
    my %second_hash;
    my %third_hash;

    foreach my $string (@strings) {
        my ($key, $value) = split /,/, $string;
        push(@{$keys_hash{$key}}, $value);
        push(@{$values_hash{$value}}, $key);
    }

    foreach my $key (keys(%keys_hash)) {
        my $found = 0;
        foreach my $value (@{$keys_hash{$key}}) {
            if (@{$values_hash{$value}} > 1) {
                if (!grep {$value} @{$second_hash{join(',', @{$values_hash{$value}})}}) {
                    push(@{$second_hash{join(',', @{$values_hash{$value}})}}, $value);
                }
                $found = 1;
            }
        }
        if (!$found) {
            $second_hash{$key} = $keys_hash{$key};
        }
    }

    %third_hash = map { $_ => join(',',@{$second_hash{$_}}) } keys(%second_hash);

    return \%third_hash;
}

print Dumper compress_strings( 'a,1', 'a,2', 'b,1', 'c,2', 'd,4' );
print Dumper compress_strings( 'a,1', 'a,2', 'b,3', 'c,3' );
print Dumper compress_strings( 'a,1', 'b,1' ,'b,2' ,'c,1' ,'c,2' ,'d,2' ,'d,3' ,'d,4' ,'e,3' ,'e,4' ,'e,5' );

输出:

$VAR1 = {
          'a,c' => '2',
          'a,b' => '1',
          'd' => '4'
        };
$VAR1 = {
          'a' => '1,2',
          'b,c' => '3'
        };
$VAR1 = {
          'a,b,c' => '1',
          'b,c,d' => '2',
          'd,e' => '3'
        };