文字列リストをTRIE Optimizeされた正規表現に
Posted feedbacks - Other
1文字ずつのツリーを作って、子を1つしかもたない親に子をくっつけて、参考ページにあるようなTrieツリーにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import sys
def get_chr_tree(strs, before=""):
index = len(before)
s = set([str[index] for str in strs if len(str) > index and str[:index]==before])
l = [get_chr_tree(strs, before+c) for c in s]
return [before[-1]] + l if before else l[0]
def merge_chr(chr_tree):
try:
if len(chr_tree) == 2:
return merge_chr([chr_tree[0]+chr_tree[1][0]] + chr_tree[1][1:])
else: return [chr_tree[0]] + [merge_chr(tree) for tree in chr_tree[1:]]
except IndexError:
return chr_tree
def to_regexp(chr_tree):
def make_regexp(chr_tree):
if len(chr_tree) == 1: return chr_tree[0]
else:
hatena = "?" if [True for l in chr_tree[1:] if "\n" in l] else ""
try:
inner = "".join(["|" + make_regexp(tree) for tree in chr_tree[1:]])
except IndexError:
print "IndexError",chr_tree
inner = ""
return chr_tree[0] + "(?:" + inner + ")" + hatena
return "(?-xism:" + make_regexp(chr_tree).replace("|\n", "").replace("\n", "").replace(":|", ":") + ")"
words = []
for line in sys.stdin: words.append(line)
chr_tree = get_chr_tree(words)
merged_chr_tree = merge_chr(chr_tree)
print to_regexp(merged_chr_tree) # => (?-xism:program(?:m(?:a(?:ti(?:c(?:ally)?|st)|r)?|er)|ist(?:ic)?)?)
|

dankogai
#4038()
[
Perl
]
Rating0/2=0.00
これは、実例を見た方が簡単だと思います。 CPANにRegexp::Assembleというモジュールがあるのですが、要はこれの簡易版を作って欲しいということです。私自身、同様のことを行うモジュールを過去にいくつか作っています(e.g Regexp::Optimizer)。
ここでは、文字列のリストを受け取って、それをTRIE化した正規表現に出来ればOKです。Regexp::AssembleやRegexp::Optimizerは正規表現を受け取ってそれをTrie化することも可能ですし、Perl 5.10では内部的にTrie Optimizationを行ったりするのですが、そこまでの機能は求めません。
なお、ここで言う「正規表現」は、必ずしもPerl互換のものである必要はありません。それがTrieになっていることをきちんと示せればOKです。
とはいうものの、Perl5互換になっていた方が、サポートしている環境が多くて有用性は高そうです。可能であればそうして下さい。
Dan the Regexp Assembler
see: Trie (en.wikipedia)
Rating0/2=0.00-0+
[ reply ]