我在一些代码上遇到了一些麻烦。请记住,我是一个糟糕的程序员,所以我的解决方案可能不是很有说服力(这可能是我内存不足的原因 - 我有 4 GB 并且脚本会慢慢填充它)。
这就是问题所在。我在一个目录中有大约 3,500 个文件。每个文件由一行组成,该行可以包含相对较少或许多没有空格的字符(最小的文件为 200 字节,而最大的文件为 1.3 兆字节)。我想要做的是在设定长度的两个文件之间找到一个公共子字符串(在下面的代码中它是 13 个字符)。我一次做两个,因为我不是在所有这些中寻找一个共同的子字符串,而是在比较所有文件之前两个的组合。即,文件之间设置长度的任何公共子字符串,而不是所有文件共有的子字符串。
我使用了一个包装了 C 实现的后缀树模块(在这里)。首先,我列出目录中的所有文件,然后查找两个文件的组合以覆盖所有组合,一次将两个文件传递给后缀树,然后查找作为公共子字符串的序列。
但是,我真的不知道为什么它会慢慢耗尽内存。我希望我们可以对代码进行修改,以便它以某种方式清除未使用内容的内存?显然,处理 3,500 个文件需要很长时间,但我希望无需增量填充 4 GB 内存就可以做到。任何帮助将不胜感激!这是我到目前为止的代码:
from suffix_tree import GeneralisedSuffixTree
from itertools import combinations
import glob, hashlib, os
alist = open('tmp.adjlist', 'w')
def read_f(f):
f = open(f, "r")
s = str(f.readlines())
f.close()
return s
def read_gs(a,b):
s1 = read_f(a)
s2 = read_f(b)
print str(a) + ":" + str(hashlib.md5(s1).hexdigest()) + " --- " + str(b) + ":" + str(hashlib.md5(s2).hexdigest())
return [s1,s2]
def build_tree(s):
hlist = []
stree = GeneralisedSuffixTree(s)
for shared in stree.sharedSubstrings(13):
for seq,start,stop in shared:
hlist.append(hashlib.md5(stree.sequences[seq]).hexdigest())
hlist = list(set(hlist))
for h in hlist:
alist.write(str(h) + " ")
alist.write('\n')
glist = []
for g in glob.glob("*.g"):
glist.append(g)
for a,b in list(combinations(glist, 2)):
s = read_gs(a,b)
build_tree(s)
alist.close()
os.system("uniq tmp.adjlist network.adjlist && rm tmp.adjlist")
更新#1
这是更新的代码。我添加了 Pyrce 提出的建议。然而,在 jogojapan 发现 C 代码中的内存泄漏之后,鉴于这超出了我的专业知识范围,我最终采用了一种慢得多的方法。如果有人在这方面知识渊博,我真的很想知道如何修改 C 代码以修复内存泄漏或释放函数,因为我认为 Python 的 C 后缀树绑定非常有价值。在没有后缀树的情况下通过这个脚本运行数据可能需要几天时间,所以我绝对愿意看看是否有人有创造性的修复!
from itertools import combinations
import glob, hashlib, os
def read_f(f):
with open(f, "r") as openf:
s = str(openf.readlines())
return s
def read_gs(a,b):
s1 = read_f(a)
s2 = read_f(b)
print str(a) + ":" + str(hashlib.md5(s1).hexdigest()) + " --- " + str(b) + ":" + str(hashlib.md5(s2).hexdigest())
return [s1,s2]
def lcs(S1, S2):
M = [[0]*(1+len(S2)) for i in xrange(1+len(S1))]
longest, x_longest = 0, 0
for x in xrange(1,1+len(S1)):
for y in xrange(1,1+len(S2)):
if S1[x-1] == S2[y-1]:
M[x][y] = M[x-1][y-1] + 1
if M[x][y]>longest:
longest = M[x][y]
x_longest = x
else:
M[x][y] = 0
return S1[x_longest-longest: x_longest]
glist = glob.glob("*.g")
for a,b in combinations(glist, 2):
s = read_gs(a,b)
p = lcs(s[0],s[1])
if p != "" and len(p) >= 13:
with open("tmp.adjlist", "a") as openf:
openf.write(hashlib.md5(s[1]).hexdigest() + " " + hashlib.md5(s[0]).hexdigest() + "\n")
os.system("uniq tmp.adjlist network.adjlist && rm tmp.adjlist")