Dato che vuoi "convertire regex in DFA in meno di 30 minuti", suppongo che tu stia lavorando a mano su esempi relativamente piccoli.
In questo caso puoi usare l'algoritmo di Brzozowski , che calcola direttamente l'automa Nerode di una lingua (che è noto essere uguale al suo automa deterministico minimo). Si basa su un calcolo diretto dei derivati e funziona anche per espressioni regolari estese che consentono l'intersezione e la complementazione. Lo svantaggio di questo algoritmo è che richiede di verificare l'equivalenza delle espressioni calcolate lungo la strada, un processo costoso. Ma in pratica, e per piccoli esempi, è molto efficiente.[ 1 ]
Quozienti a sinistra . Let sia un linguaggio di e lasciare che essere una parola. Allora
Il linguaggio è chiamato un quoziente di sinistra (o sinistra derivato ) di .A ∗ u u - 1 L = { v ∈ A ∗ ∣ u v ∈ L } u - 1 L LLUN*u
u- 1L = { v ∈ A*∣ u v ∈ L }
u- 1LL
Automa di Nerode . L' automa Nerode di è l'automa deterministico dove , e la funzione di transizione è definita, per ogni , dalla formula
Attenzione a questa definizione piuttosto astratta. Ogni stato di è un quoziente sinistro di di una parola, e quindi è una lingua di . Lo stato iniziale è la lingua , e l'insieme degli stati finali è l'insieme di tutti i quozienti di sinistra diA ( L ) = ( Q , A , ⋅ , L , F ) Q = { u - 1 L ∣ u ∈ A ∗ } F = { u - 1 L ∣ u ∈ L } a ∈ A ( u - 1 L ) ⋅ a = a - 1 ( u - 1LUN( L ) = ( Q , A , ⋅ , L , F)Q = { u- 1L ∣ u ∈ A*}F= { u- 1L ∣ u ∈ L }a ∈ A
( u- 1L ) ⋅ a = a- 1( u- 1L ) = ( u a )- 1L
UNLUN*LL per una parola di .
L
L'algoritmo di Brzozowski . Lascia che siano lettere. Si possono calcolare i quozienti di sinistra usando le seguenti formule:
a , b
un'- 11un'- 1( L1∪ L2)un'- 1( L1∩ L2)= 0= a- 1L1∪ u- 1L2,= a- 1L1∩ u-1L2,un'-1Bun'-1(L1∖ L2)un'- 1L*= { 10se a = bse a ≠ b= a- 1L1∖ u- 1L2,= ( a- 1L ) L*
un'- 1( L1L2)= { ( a- 1L1) L2( a- 1L1) L2∪ a- 1L2si 1 ∉ L1,si 1 ∈ L1
Esempio . Per , otteniamo in successione:
che fornisce il seguente automa minimo.
L = ( a ( a b )*)*∪ ( b a )*
1- 1Lun'- 1L1B- 1L1un'- 1L2B- 1L2un'- 1L3B- 1L3un'- 1L4B- 1L4un'- 1L5B- 1L5= L = L1= ( a b )*( a ( a b )*)*= L2= a ( b a )*= L3= b ( a b )*( a ( a b)*)*∪ ( a b )*( a ( a b)*)*= b L2∪L2=L4= ∅= ( b a )*= L5= ∅= a- 1( b L2∪ L2) = a- 1L2=L4=b-1(b L2∪L2) = L2∪ b- 1L2=L2= ∅= a ( b a)*=L3
[ 1 ] J. Brzozowski, Derivatives of Regular Expressions, J.ACM 11 (4), 481–494, 1964.
Modifica . (5 aprile 2015) Ho appena scoperto che una domanda simile: quali algoritmi esistono per la costruzione di un DFA che riconosce il linguaggio descritto da una data regex? è stato chiesto su cstheory. La risposta affronta in parte i problemi di complessità.
a(a|ab|ac)*a+
. Puoi tradurlo direttamente in un NDFA che riduci in un DFA, oppure puoi normalizzarlo in qualcosa che si associa immediatamente a un DFA.