Note
DFA vs NFA: What's the Difference?
Deterministic and nondeterministic finite automata accept exactly the same languages, but they model computation very differently. Here's how to tell them apart, and when to reach for each.
A DFA (deterministic finite automaton) and an NFA (nondeterministic finite automaton) both recognize regular languages, and it turns out they recognize exactly the same class of languages. The difference isn't in what they can express. It's in how they get there.
What Makes a DFA Deterministic
A DFA is defined by five components, (Q, Σ, δ, q0, F), where the transition
function δ: Q × Σ → Q is total: every state has
exactly one outgoing transition for every symbol in the alphabet, and
nothing else. Given an input string, a DFA has exactly one possible path
through its states. There's never a choice to make, which is what makes it
fast to simulate: you just follow the single active state, symbol by
symbol.
What Makes an NFA Nondeterministic
An NFA relaxes that rule. Its transition function
δ: Q × Σ → P(Q) can send a state to zero, one, or many next
states on the same symbol, and it can also take ε
(epsilon) transitions that consume no input at all. A string is accepted if
at least one of the possible paths through the machine ends in an
accepting state. The NFA is allowed to "guess" and only has to be right
once.
Same Power, Different Shape
The theorem proved by Rabin and Scott guarantees that every NFA has an equivalent DFA:
you can always convert one to the other via
subset construction.
So neither model recognizes a larger class of languages than the other.
What changes is the size of the machine: a DFA built from an NFA with
n states can need up to 2ⁿ states in the worst
case, since each DFA state corresponds to a subset of NFA states.
When to Reach for Each
- NFAs are easier to build by hand or generate from a regular expression: union, concatenation, and Kleene star all have simple NFA constructions that just wire machines together.
- DFAs are cheaper to run: one active state, one transition lookup per symbol, no backtracking. That's why lexers and string matching engines compile down to DFAs even when the pattern was written as a regex (i.e. an NFA in disguise).
A Concrete Example
Take the language over {a, b} of strings that contain the
substring ab. As an NFA, this is three states: stay in
q0 on anything, guess that an a starts the match
and move to q1, then on b move to the accepting
state q2 and stay there forever. The determinized version
needs a fourth state to track "have I already seen the match," but the
idea is identical. The DFA just has to carry that extra bit of memory
explicitly instead of getting to guess.
Build both versions on the canvas and step through the same input string. Watching the NFA explore multiple states at once next to the DFA's single active state is the fastest way to make the distinction click.