1行の文字列で構成される約3,500個のファイルがあります。ファイルのサイズはさまざまです(約200bから1mb)。各ファイルを他のファイルと比較して、2つのファイル間で長さが20文字の共通のサブシーケンスを見つけようとしています。サブシーケンスは、各比較中に2つのファイル間でのみ共通であり、すべてのファイル間で共通ではないことに注意してください。
私はこの問題に少し苦労しました、そして私は専門家ではないので、私は少しアドホックな解決策に行き着きました。itertools.combinationsを使用して、Pythonでリストを作成します。リストの組み合わせは約6,239,278になります。次に、ファイルを一度に2つずつ、 libstreeと呼ばれるCで記述されたサフィックスツリーライブラリのラッパーとして機能するPerlスクリプトに渡します。私はこのタイプの解決策を避けようとしましたが、Pythonで唯一の同等のCサフィックスツリーラッパーがメモリリークに悩まされています。
これが私の問題です。私はそれを計時しました、そして私のマシンでは、ソリューションは25秒で約500の比較を処理します。つまり、タスクを完了するには、約3日間の連続処理が必要になります。そして、20文字ではなく25文字を確認するために、もう一度すべてを行う必要があります。私は自分の快適ゾーンから外れていて、あまり優れたプログラマーではないことに注意してください。したがって、はるかにエレガントな方法があると確信しています。これをする。ここで質問してコードを作成し、このタスクをより速く完了する方法について誰かが提案を持っているかどうかを確認したいと思いました。
Pythonコード:
from itertools import combinations
import glob, subprocess
glist = glob.glob("Data/*.g")
i = 0
for a,b in combinations(glist, 2):
i += 1
p = subprocess.Popen(["perl", "suffix_tree.pl", a, b, "20"], shell=False, stdout=subprocess.PIPE)
p = p.stdout.read()
a = a.split("/")
b = b.split("/")
a = a[1].split(".")
b = b[1].split(".")
print str(i) + ":" + str(a[0]) + " --- " + str(b[0])
if p != "" and len(p) == 20:
with open("tmp.list", "a") as openf:
openf.write(a[0] + " " + b[0] + "\n")
Perlコード:
use strict;
use Tree::Suffix;
open FILE, "<$ARGV[0]";
my $a = do { local $/; <FILE> };
open FILE, "<$ARGV[1]";
my $b = do { local $/; <FILE> };
my @g = ($a,$b);
my $st = Tree::Suffix->new(@g);
my ($c) = $st->lcs($ARGV[2],-1);
print "$c";