文字列リストをTRIE Optimizeされた正規表現に
Posted feedbacks - Haskell
Text.RegexモジュールではデフォルトではPOSIXの正規表現をつかっている. ここではそれにしたがった正規表現文字列を生成する. メタ文字のエスケープもしたつもり. 実行結果 *Main> putStrLn $ oregex (unfoldTree phi sample) "" program(ist(ic)?|m(a(r|ti(c(ally)?|st))?|er))?
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 Data.List
import Data.Tree
type Trie = Tree (Bool,String)
eqapp f x y = f x == f y
lcp :: [String] -> (String, [String])
lcp [] = ("",[])
lcp xxs@(x:xs)
= if null x
then ("",xxs)
else if all (isPrefixOf [head x]) xs
then case lcp (map tail xxs) of
(ps,yys) -> (head x:ps,yys)
else ("",xxs)
phi :: [String] -> ((Bool,String), [[String]])
phi [x] = ((False,x), [])
phi xxs = case lcp xxs of
(ps,"":ys) -> ((True,ps), groupBy (eqapp head) ys)
(ps,yys) -> ((False,ps),groupBy (eqapp head) yys)
oregex :: Trie -> ShowS
oregex (Node (p,s) [])
| p = showString (escape s) . showString "?"
| otherwise = showString (escape s)
oregex (Node (p,s) cs)
| p = (showString (escape s) .) $ (. showString "?") $ paren $ foldr (.) id (intersperse (showString "|") (map oregex cs))
| otherwise = (showString (escape s) .) $ paren $ foldr (.) id (intersperse (showString "|") (map oregex cs))
paren :: ShowS -> ShowS
paren s = showString "(" . s . showString ")"
metaChars = "\\|[](){}.*+?^$"
escapeMeta c | elem c metaChars = '\\':[c]
| otherwise = [c]
escape = concatMap escapeMeta
sample = sort ["program"
,"programist"
,"programistic"
,"programma"
,"programmar"
,"programmatic"
,"programmatically"
,"programmatist"
,"programmer"
]
|


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 ]