文字列リストをTRIE Optimizeされた正規表現に
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の総称で再帰的なデータ構造を表現する事はできないのでしょうか(この例ではキャストで逃げています)。
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());
}
}
|


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 ]