我有一堆串成串的字符串 例如,这些是三对。第一个有两个字符串" 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}
压缩数据的最佳算法是什么?
答案 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'
};