我们如何引用文件的特定行?

时间:2013-01-14 18:49:19

标签: java algorithm file data-structures hash

我正在阅读算法问题,其中一个是:

  

拥有包含数百万行数据的文件,共有2行   是相同的。线条很长,可能不适合记忆。找   两条相同的线。

建议的解决方案是读取部分行并为每行创建散列 例如。通过构建第1行的第1部分(可以在内存中读取)的散列,然后将第1行的第2部分哈希到第1行的第N部分,构建第1行的哈希值。
将哈希值存储在文件或哈希表​​中。对于任何相同的哈希值,比较行。如果线条相同,我们就解决了。

虽然我对高级别的解决方案有所了解,但我不知道如何实现这一点。我们如何将哈希与文件中的特定行相关联?这种语言实现细节吗?
例如。在Java中我们如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

真正的答案是购买更多内存。这些天你可以在Java 2 GB中使用最长的字符串并且适合机器。您可以以低于200美元的价格购买32 GB。


但要解决问题,我建议你

  • 找到每一行的偏移量。
  • 找到长度相同的行(使用偏移的差异)
  • 计算具有相同长度的行的64位或更长的哈希值。
  • 对于具有相同散列的行,进行逐字节比较。

注意:如果没有足够的内存来缓存整个文件,则需要很长时间。如果你有一台32 GB的机器并且它有一个64 GB的文件,那么每次通过大约需要20分钟,而且这有多次通过。


  

1)找到偏移量的API?

您计算已读取的字节数,即偏移量。

  

2)真正的答案是购买更多内存项目经理不同意真实产品。你有不同的经历吗?

我向他们指出,我可以花一天时间来支付他们费用> 1000美元(即使这不是我得到的报酬)如果认为可以很好地利用资源,可以节省100美元的可重用内存。我让他们决定;)

我8岁的儿子在他制造的PC中有8 GB,因为内存花费我24英镑。然而,你是对的,有些项目经理认为8 GB对于专业人士来说太过分了,每小时花费他们多少钱!我在PC上有16 GB,我不会用它来运行任何严重的东西,因为我在256 GB的机器上工作。这些天您可以购买2 TB的机器,这对于大多数应用来说都是过度的。 ;)

答案 1 :(得分:0)

虽然我同意解决方案是利用现代技术,并利用现在的廉价记忆,但问题是如何运用头脑并理解如何在给定约束下解决问题。

你谈到的哈希很简单。 java解决方案可以利用引擎盖下的一些内容,这些内容可能会掩盖实际发生的事情,因此我将首先解释解决方案,然后再解释java实现。

通用解决方案:

哈希,例如SHA1,MD5等,通过压缩输入生成一个整数。假设您只能在每行中存储第一个MB字符。

  • 您将迭代每一行,获取第一个MB字符,然后将其传递给哈希算法(例如MD5)。
  • 然后,您将散列映射为键,将行号列表/数组映射为值。
  • 第一次传递后,任何具有匹配的第一个MB字符的行将以相同的哈希结束,因此在地图中的相同列表中。
  • 要准备第二遍,请搜索地图并剔除任何只包含一个行号的列表。
  • 然后通过编辑地图中其余条目的行号来创建行号列表,这些行将是第二行中唯一检查的行。
  • 第二遍,你从行列表中的每一行拉出第二个MB字符,哈希并将它们放在地图中,方式与第一行相同。
  • 迭代地图中的条目,剔除只有一个行号的哈希条目。
  • 重复第二步,但增加字符块(MB)以与传递号一致。
  • 当你到达一个只有一个带有多个行号的散列的通行证,并且该散列只有两个元素时,那些行是两个相同的行。

这实质上是树搜索。

Java方法: Java有一个名为HashMap的类,它自动散列密钥。使用

HashMap<String,ArrayList<Integer>>

对于您的主地图,您只需要进行每次调用

  • map.get(mbBlock)。新增(LINENUMBER);当然你应该检查这是否是第一次使用这个键所以你没有得到空指针异常。
  • 每次传递后,剔除只包含一行的条目。
  • 重复剩余的行,直到您只剩下两个行号

答案 2 :(得分:0)

  1. 获取每行的前k个字符,其中k是可配置的。您的哈希值可以找到几组可以包含相同行的行。

  2. 根据第一步的结果,您可以在其中缩小搜索范围,在下一个k个字符的每个较小的组上运行算法。

  3. 如果不是在最糟糕的情况下,搜索范围在每轮之后会大幅缩小。

  4. 算法的诀窍在于将大问题分解为小问题并充分利用前面步骤的结果。