challenge 文字列リストをTRIE Optimizeされた正規表現に

これは、実例を見た方が簡単だと思います。 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

 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
#!/usr/local/bin/perl
use strict;
use warnings;
use Regexp::Assemble;

my $ra = Regexp::Assemble->new;
while(<>){
    chomp;
    next unless $_;
    $ra->add($_);
}
print $ra->re, "\n"
__END__

% grep program /usr/share/dict/words 
program
programist
programistic
programma
programmar
programmatic
programmatically
programmatist
programmer

% grep program /usr/share/dict/words | perl sample.pl 
(?-xism:program(?:m(?:a(?:ti(?:c(?:ally)?|st)|r)?|er)|ist(?:ic)?)?)

Posted feedbacks - Java

引数で与えられた文字列(のみ)にマッチする正規表現を生成します。生成される正規表現はPerl互換のはずです(Javaで動作する事は確認してあります)。

program
programist
programistic
programma
programmar
programmatic
programmatically
programmatist
programmer
を与えた場合は、
program(?:|ist(?:|ic)|m(?:a(?:|r|ti(?:c(?:|ally)|st))|er))
を生成します。

#Javaの総称で再帰的なデータ構造を表現する事はできないのでしょうか(この例ではキャストで逃げています)。
 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.*;

@SuppressWarnings("unckecked")
public class Trie {
    public static final String MUST_ESCAPE = "()[]\\.+*?|";
    private Map<Character, Map> trie = new TreeMap<Character, Map>();
    public void add(String str) {
        Map<Character, Map> t = trie;
        for (char c : str.toCharArray()) {
            if (t.containsKey(c)) {
                t = (Map<Character, Map>)t.get(c);
            } else {
                Map<Character, Map> t2 = new TreeMap<Character, Map>();
                t.put(c, t2);
                t = t2;
            }
        }
        t.put('\0', null);
    }
    public String toRegex() {
        return toRegex(trie).toString();
    }
    private StringBuilder toRegex(Map<Character, Map> t) {
        StringBuilder sb = new StringBuilder();
        Set<Character> keys = t.keySet();
        if (keys.size() > 1)
            sb.append("(?:");
        Iterator<Character> i = keys.iterator();
        while (i.hasNext()) {
            char c = i.next();
            if (c != '\0') {
                if (MUST_ESCAPE.indexOf(c) >= 0)
                    sb.append('\\');
                sb.append(c);
                sb.append(toRegex(t.get(c)));
            }
            if (i.hasNext())
                sb.append('|');
        }
        if (keys.size() > 1)
            sb.append(")");
        return sb;
    }
    public static void main(String[] args) {
        Trie t = new Trie();
        for (String str : args) {
            t.add(str);
        }
        System.out.println(t.toRegex());
    }
}

Index

Feed

Other

Link

Pathtraq

loading...