3TB TXT文件中的重复字符串

时间:2010-09-09 07:56:35

标签: c# java algorithm

假设有一个3TB TXT文件,其中每一行都是一个字符串,如何在其中找到那些重复的字符串?这是我朋友的采访问题。在接下来的一次采访中,我们最好让这些问题足够清楚。

PS:如果我是受访者,我会告诉采访者:你们怎么能在TXT文件中存储这么多字符串?这真是一个坏主意!

11 个答案:

答案 0 :(得分:5)

一种可能性是使用布隆过滤器。

布隆过滤器很快(就像使用哈希码一样)并且没有假阴性。它也非常节省空间。可以调整各种参数(大小(m)和函数数量(k))以便以大小和时间为代价实现更好的误报率。

将所有字符串逐个添加到过滤器所代表的集合中。在插入时,您可以确定是否存在重复项。由于它没有漏报,你只需要仔细检查过滤器出现的“重复”字符串。

如果您想了解有关Bloom过滤器的更多信息,请转至wikipedia

这是解决此问题的最佳方法。代理服务器使用Bloom过滤器来确定URL是否在其缓存中。代理服务器看到数十亿个URL,并且需要能够非常快速地告知URL是新的还是以前被“看到”的。如果URL是“新”,则代理服务器立即从原始URL中提取网站,而不是在其缓存中查找。

这里的所有其他答案甚至远程使用“排序”显然是错误的。

答案 1 :(得分:4)

sort bigfile.txt | uniq -d

答案 2 :(得分:3)

如果每行只有一个单词,为什么你不只是将文本文件转储到数据库表中,其中包含以下列id,text并做一些

select text, count(text) 
from table 
group by text
having count(text)>1
那么你应该以一种非常简单的方式得到正确的答案。

答案 3 :(得分:1)

一种相当直接的方式:

您可以合并文本文件的排序(对于太大而无法容纳主内存的数据的良好性能)。然后,您可以通过文件一次性识别重复项。 O(nlogn)。当然,这将修改原始文本文件,或者您可以复制。

答案 4 :(得分:1)

如果你有足够的额外磁盘空间,这样的事情应该是可行的:

for every line in the file:
    calculate a hash function for that line.
    append to a file named based on that hash (create if new).
for every file created:
    sort it.
    for every line in sorted file:
        if first line in file:
            set count to 0.
            set lastline to line.
        else
            if line identical to lastline:
                add 1 to count.
                if count is 1:
                    Output line.
            else:
                set count to 0.
        set lastline to line.

假设您的哈希函数相对平衡,那么排序不应太繁琐。

答案 5 :(得分:1)

SELECT String
FROM TextFile
GROUP BY String
HAVING COUNT(*) > 1
ORDER BY String

答案 6 :(得分:0)

速度算吗?

我想到的一个明显的解决方案是将前1000行加载到某种类Set类中,然后一次读取剩余的行,并检查它们是否包含在组。然后读取下一行1000行,然后重复。这样,你一次只能在内存中存储1000行。

我不认为你会告诉采访者将大量数据存储在文本文件中是个不错的主意。谁知道这个文本文件是怎么来的...也许是一些遗留系统的结果,或者谁知道什么。它的存在是完全合理的原因。

答案 7 :(得分:0)

对此文件进行排序,重复项将一起排序。或者,创建第二个文件并将每行哈希(md5?)放入其中,然后对其进行排序。

答案 8 :(得分:0)

我建议2个解决方案。

第一种方法是将每一行放入集合中,然后查看集合,查找具有多个元素的集合。我有解决方案将集合写入磁盘以节省内存空间。

第二种方法是像其他人一样建议对文本文件进行排序。

答案 9 :(得分:0)

概率解决方案

以下技术尝试使用哈希函数来识别经证明是唯一的字符串。在第一次传递之后,字符串将被分为(1)证明唯一和(2)可能重复。

由于哈希码冲突,会有许多标记为可能重复的唯一字符串。后续传递仅适用于可能重复的字符串,以降低冲突率。

这种技术并不能保证摆脱所有重复(只是其中大部分)。

  1. s [1],s [2],...,s [n]是输入字符串。
  2. h [1],h [2],...,h [m]是大小为k的不同散列函数。
  3. a [1,... n]是具有值0,1的比特阵列。
  4. b [1,...,m] [1,...,k]是一个值为0,1,2的标志数组。
  5. 然后

    1. 对于i = 1到k:
      1. 对于j = 1到n:
        1. 如果a [j] == 0 //此字符串可能/可能不唯一
          1. 设x为h [i](s [j])。
          2. 如果b [i] [x] == 0则b [i] [x] == 1
          3. 如果b [i] [x] == 1则b [i] [x] = 2
        2. 如果[j] == 1,则此字符串已被证明是唯一的,跳过它。
      2. 对于j = 1到n:
        1. 如果a [j] == 0 //此字符串可能/可能不唯一
          1. 令x为h [i](s [j])
          2. 如果b [i] [x] == 1则设置[j] = 1 //我们已证明该字符串是唯一的
          3. 如果b [i] [x] == 2,则此字符串可能/可能不是唯一的
          4. 如果b [i] [x] == 0则存在实施问题
        2. 如果[j] == 1,则此字符串已被证明是唯一的,跳过它

答案 10 :(得分:0)

我认为使用perl会更好,因为它可以用于文本处理 在perl程序中写下以下内容:


我的%dataHash =();#创建你的哈希
while(@ARGV){#argv是命令行arg,它将是3TB文件     格格($ _); #remove the new line

if(!exists($ dataHash {$ _})){
      $ dataHash {$ _} = $ currentLine;如果密钥存在,则#increase key的值计数...处理重复....
    };     $ currentLine ++;
  }; #end而

现在我们可以做任何我们想要的事情......比如我们想要重复的 所以我们可以做的是运行for循环并检查值大于0的所有键是重复的......就是这样


我认为应该这样做...抱歉不为程序添加颜色以提高可读性