一般に、DFAは高速ですが、NFAはよりコンパクトです。 NFAは、正規表現のサイズに比例します。 (非形式的な証明:正規表現の構文の各演算子ノードは、NFAグラフに新しいノードを追加するだけです).DFAはNFA状態の集合の部分集合から形成されるため、かなり大きくなる場合があります。最悪の場合、DFAは正規表現で指数関数的にサイズ変更されます。これの例は、(a|b)(a|b)(a|b)(a|b)...(a|b)
という形式の表現で、N (a|b)
単位は、サイズがO(2 ** N)であるDFAに変換されます。これには、a
とb
のすべての組み合わせの固有の状態を通る遷移が含まれます。同等のNFAをキャッシュに適合させるために必要なデータ構造がある場合、縮退したDFAがCPUキャッシュのサイズを超える可能性があります。
余分な手順があるため、DFAにいくらか手間がかかります。したがって、トレードオフが適用されます:DFAの構築を正当化するのに十分なデータがNFAシミュレータによって処理されます。
NFAシミュレーションでは、入力にまったく当てはまらない正規表現の部分に触れることを完全に避けることができます。たとえば、正規表現の形式がR1 | R2で、R1が非常に単純で小さく、R2が巨大で複雑な獣であるとします。入力が通常、R1とR2にほとんど一致しないと仮定します(たとえば、接頭辞の不一致により、入力の一部がまったくない)。これはトレードオフに影響します.DFAへのコンパイルは、すべてがコンパイルされ、単純なR1部分と怪物R2部分を意味します。
最後に、実装は厳密にNFAまたはDFAである必要はありません。 NFAシミュレータcan cache the stateが計算するものを設定します。これらのキャッシュされた状態はDFAの状態と同等であり、DFAへのコンパイルと同様の利点があります。あなたはこれが "NFAのためのJIT"だと考えることができます。キャッシュはある固定サイズにトリムされ、置き換えポリシーに従うことができるので、完全なDFAが大きい式は少ないメモリ量で処理できます(データがキャッシュ内の参照の局所性が高い場合はほぼ同じ速度で処理できます) 。
出典
2016-06-18 00:37:29
Kaz
質問が広すぎます。 "どちらが速いの?"無効な質問です。彼らはそれぞれ特定のタスクに適しており、場合によっては両方とも必要でもあります。 – naomik
NFAをシミュレートすると、他の状態から1つの状態から1つだけ遷移します。ただし、状態は集合として表されます。それらは、遷移表から引き出された単なる整数ではありません。 – Kaz