超大字符串子集的比较

时间:2014-04-02 09:42:50

标签: algorithm string-comparison large-data

大家好:)我真的很困惑一个任务: - /

每天有一个2000000到4000000个字符串的文件,其中包含一行一行的15个符号,如下所示:

850025000010145
401115000010152
400025000010166
770025555010152
512498004158752

从今年年初开始,您会有相应数量的此类文件。因此,我必须将今天文件的每一行与今年年初的所有先前文件进行比较,并仅返回所有已检查文件中之前从未遇到的数字。

我应该使用哪种语言和算法?如何实现呢?

3 个答案:

答案 0 :(得分:3)

您应该能够执行此操作,而无需编写除简单脚本之外的任何代码(即bash,Windows批处理,Powershell等)。有一些标准工具可以快速完成这类工作。

首先,您有一些包含200万到400万个数字的文件。使用所有这些文件很困难,因此您要做的第一件事就是创建一个已排序的组合文件。这种简单的方法是将所有文件连接成一个文件,对其进行排序,并删除重复项。例如,使用GNU / Linux catsort命令:

cat file1 file2 file3 file4 > combined
sort -u combined > combined_sort

-u删除重复项)

该方法的问题在于您最终会对非常大的文件进行排序。图4百万行,每行15个字符,加上换行符,几乎100天的文件,并且您正在使用7千兆字节。一整年的数据将是25千兆字节。这需要很长时间。

因此,对每个单独的文件进行排序,然后将它们合并:

sort -u file1 >file1_sort
sort -u file2 >file2_sort
...
sort -m -u file1 file2 file3 > combined_sorted

-m开关合并已经排序的文件。

现在你拥有的是到目前为止你所见过的所有标识符的排序列表。您想要将今天的文件与之进行比较。首先,排序今天的文件:

sort -u today >today_sort

现在,您可以比较文件并仅输出今天文件的唯一文件:

comm -2 -3 today_sort combined_sort

-2表示仅限制在第二个文件中出现的行,而-3表示要抑制两个文件共有的行。所以你得到的是today_sort中不存在combined_sort中的行。

现在,如果您每天都要这样做,那么您需要从comm命令获取输出并将其与combined_sort合并,以便您可以使用该组合文件明天。这可以防止您每天必须重建combined_sort文件。所以:

comm -2 -3 today_sort combined_sort > new_values

然后:

sort -m combined_sort new_values > combined_sort_new

您可能希望使用日期为文件命名,因此您需要combined_sort_20140401combined_sort_20140402等。

因此,如果您在年初开始并希望每天都这样做,那么您的脚本应该是这样的:

sort -u $todays_file > todays_sorted_file
comm -2 -3 todays_sorted_file $old_combined_sort > todays_uniques
sort -m $old_combined_sort todays_sorted_file > $new_combined_sort

$todays_file$old_combined_sort$new_combined_sort是您在命令行上传递的参数。因此,如果脚本被调用"每天":

daily todays_file.txt all_values_20140101 all_values_20140102

答案 1 :(得分:0)

如果你必须用手解决问题:
  - 将字符串转换为64位整数。这节省了空间(2x到4x)并加快了速度 - 计算计算   - 排序当前整数文件
  - 将当前文件与旧数据文件(已排序)合并,选择新数字

合并步骤可能看起来像MergeSort的合并步骤。  您可以将数字范围存储在单独的文件中,以避免超大文件大小。

P.S。我想建议使用位图,但它的大小约为125 TB

答案 2 :(得分:0)

一种解决方案可能是基于之前的n-1文件构建prefix tree(假设今天创建了n文件)。最耗时的构建过程只需要完成一次。构建前缀树后,可以将其另存为文件(google用于此主题)。

运行程序以检查新文件

try(BufferedReader br = new BufferedReader(new FileReader("new_file.txt"))) {
    String line = br.readLine();
    while (line != null) {
        if(!tree.contains(line)){
            counter++;
        }else{
                    tree.insert(line);
            }
        line = br.readLine();
    }
}

因此,每天运行此“伪”代码,获取唯一查询并更新树。

contains需要O(m)时间,其中m是字符数

insert也花费O(m)时间

我建议使用Java。