最も簡単なアプローチは次のとおりです。
NFA と DFA の両方で遷移のラベルとしてセグメントを使用します。たとえば、範囲 [az] は、セグメントとして表されます[97, 122]
。単一文字「a」は次のようになり[97,97]
ます。および任意の文字「.」となり[minCode, maxCode]
ます。
否定された範囲 [^az] ごとに、開始状態から次の状態への遷移が 2 回発生します。この例では、2 つのトランジション[minCode, 96]
と[123, maxCode]
を作成する必要があります。
可能なすべての文字 [abcz] を列挙することによって範囲が表される場合、文字ごとの遷移を作成するか、コードで最初に文字を範囲にグループ化して遷移の数を最適化する必要があります。したがって、[abcz] は になり[a-c]|z
ます。したがって、4 つではなく 2 つのトランジションです。
NFA にはこれで十分です。ただし、文字範囲が交差する遷移がある場合、NFA を DFA に変換するための従来のパワー セットの構築は機能しません。この問題を解決するには、追加の一般化手順が 1 つだけ必要です。すべての入力シンボルのセットが作成されると (この場合はセグメントのセットになります)、交差しないセグメントのセットに変換する必要があります。これは時間O(n*Log(n))で実行できます。ここで、n は優先順位キュー (PQ) を使用するセット内のセグメントの数であり、セグメントは左側のコンポーネントによって順序付けられます。例:
Procedure DISJOIN:
Input <- [97, 99] [97, 100] [98, 108]
Output -> [97, 97] [98, 99], [100, 100], [101, 108]
ステップ 2.「設定状態」から新しい遷移を作成するには、アルゴリズムを次のように変更する必要があります。
for each symbol in DISJOIN(input symbols)
S <- empty set of symbols
T <- empty "set state"
for each state in "set state"
for each transition in state.transitions
I <- intersection(symbol, transition.label)
if (I is not empty)
{
Add I to the set S
Add transition.To to the T
}
for each segement from DISJOIN(S)
Create transition from "set state" to T
遷移と入力記号 C を検索する際のマッチングを高速化するために、状態ごとの遷移をセグメントごとに並べ替え、二分探索を適用することができます。