Finite Automata & Regular Expressions
A mechanism-first account of regular languages through DFA and NFA state invariants, subset construction, regular-expression algebra, derivatives, Myhill–Nerode equivalence, minimization, closure, and decision procedures.
A finite automaton recognizes an unbounded input with bounded memory. Its state is not merely a node in a picture: it is the complete summary of the prefix already read that can still affect the answer. Regular expressions describe the same class of languages algebraically, while residual languages and Myhill–Nerode equivalence explain why the necessary states exist and when no finite number can suffice.
This chapter develops those views as one connected mechanism. A single running language will move through a deterministic automaton, a nondeterministic automaton, a regular expression, derivatives, and residual equivalence; each conversion comes with the invariant that makes it correct.
Words, languages, and three kinds of emptiness #
An alphabet is a finite set of symbols. A word is a finite sequence of symbols from ; is the set of all such words, including the empty word . A language is any subset .
Three notations that look like “nothing” have different meanings:
| Notation | Meaning | Contains a word? |
|---|---|---|
| the unique word of length zero | yes—exactly itself | |
| the language containing that one word | yes—one word | |
| the empty language | no |
A missing transition is different again. It may be shorthand for rejection in a partial diagram, but a formally complete DFA has a transition for every state/symbol pair, usually by routing otherwise missing cases to a rejecting sink.
Deterministic finite automata #
Extend the one-symbol transition to words:
The automaton accepts exactly when . It does not accept merely because it visited an accepting state partway through: the entire word must be consumed.
Worked invariant: words ending in 01 #
Let
Three distinct prefix summaries are sufficient:
| State | What the processed prefix currently ends with | on 0 |
on 1 |
Accepting? |
|---|---|---|---|---|
neither a useful trailing 0 nor 01 |
no | |||
0 |
no | |||
01 |
yes |
flowchart LR
start([start]) --> A(("q∅"))
A -- "0" --> B(("q0"))
A -- "1" --> A
B -- "0" --> B
B -- "1" --> C((("q01 · accept")))
C -- "0" --> B
C -- "1" --> A
The diagram is correct because the state labels are invariants. For the empty prefix, has the claimed meaning. Each table entry preserves the appropriate suffix information after appending one symbol. At end of input, exactly the prefixes in state end in 01. This induction pattern—base case, one-symbol preservation, final interpretation—is the reusable proof technique behind hand-built automata.
Nondeterminism tracks possible runs #
A nondeterministic finite automaton replaces the single next state by a set of possibilities:
After a word, the machine occupies a set of states. The word is accepted when at least one possible run ends in an accepting state. A branch that gets stuck does not reject the word if another branch succeeds.
For , an NFA can remain in a scanning state on either bit and, whenever it sees 0, also guess that this 0 begins the final suffix:
| NFA state | on 0 |
on 1 |
Accepting? |
|---|---|---|---|
| no | |||
| no | |||
| yes |
The accepting branch must finish exactly at the end of the word. Earlier guesses die when more input remains; that is harmless because continues scanning.
Some NFA definitions also permit -transitions, which change state without consuming input. That is an explicit extension, not a silent property of every NFA definition. For an -NFA, define the epsilon-closure as all states reachable from using only -transitions; close the initial set and every post-symbol set under .
Subset construction makes the uncertainty explicit #
The deterministic simulation has one state for each NFA-state set it may need to remember. If the current subset is and the next symbol is , then
For an -NFA, use and begin at . A subset is accepting iff it intersects the NFA's accepting set.
For the NFA above, only three subsets are reachable:
| DFA subset | on 0 |
on 1 |
Why it accepts |
|---|---|---|---|
| it does not | |||
| it does not | |||
| it contains |
The correctness invariant is exact:
The base case is the initial set. For the inductive step, appending follows every -transition from every state reachable after , which is precisely the union in the construction. Therefore the subset intersects exactly when the NFA has an accepting run.
An -state NFA has possible subsets, so determinization has that upper bound. It is not a prediction that all states will be reachable: the example has eight possible subsets but only three reachable ones.
Regular expressions are language algebra #
A formal regular expression denotes a language. Its atoms are:
The constructors are union, concatenation, and Kleene star:
Because the term is , every starred expression contains the empty word. Concatenation binds more tightly than union, and star binds to its immediate operand, so (0|1)*01 denotes exactly .
Two expressions are equivalent when they denote the same language, not when their syntax trees match. For example, and are semantically equivalent even though one has more syntax.
Why automata and regular expressions have equal power #
Kleene's theorem is constructive in both directions.
Expression to automaton #
Build small -NFAs for , , and each symbol. Then combine them recursively:
- Union: a fresh start has epsilon paths to both alternatives; their accepting paths lead to a fresh accept state.
- Concatenation: epsilon-connect each accepting state of the first automaton to the second's start.
- Star: a fresh start can accept immediately or enter the body; completion can exit or loop back.
Each construction mirrors the corresponding language operation. An accepting path through the union chooses one operand; through concatenation it splits into one path for each factor; through star it splits into zero or more body paths. Structural induction over the expression proves correctness. Epsilon elimination and determinization may follow, but they are not what makes the construction correct.
Automaton to expression #
A generalized NFA labels an edge by a regular expression rather than one symbol. Add a unique start and accept state, then eliminate internal states. When removing , update every remaining edge by
The two alternatives are exactly the paths that avoid and the paths that enter , loop there zero or more times, and leave. The invariant is that each label denotes all paths between its endpoints whose eliminated internal states come from the set processed so far. Once only start and accept remain, their edge denotes the automaton's language.
Elimination order can radically change expression size without changing its denotation. A larger result is not a different language.
Derivatives turn prefixes into states #
The left derivative of a language by a word is its residual future:
Brzozowski's derivative is a regular expression denoting . Define nullable as the predicate that is true exactly when . Then the central rules are:
Differentiate successively by each symbol of . Then
This is already a DFA construction: normalized derivative languages are states, taking a derivative is a transition, and nullable derivatives are accepting. The word “normalized” matters. Raw expression syntax can grow indefinitely even though a regular language has only finitely many distinct residual languages.
For (0|1)*01, the semantic derivative states correspond to the same three questions as the hand-built DFA:
| Residual state | What a continuation must do |
|---|---|
eventually finish with 01, with no useful trailing 0 yet |
|
either use the existing trailing 0 followed by 1, or later create a new final 01 |
|
may stop now, or continue and later create a new final 01 |
The automaton state is therefore literally a future language.
Myhill–Nerode explains minimality #
For a language , define right-context equivalence on prefixes:
Two prefixes are equivalent when no future suffix can distinguish them. The relation is right-invariant: appending the same symbol to equivalent prefixes keeps them equivalent.
Why both directions hold:
- Any DFA puts two prefixes in the same class whenever they reach the same state, because all future transitions are then identical. A finite DFA therefore induces only finitely many future behaviors.
- If has finitely many classes, use those classes as states. Appending sends to ; right invariance makes this well-defined. Mark accepting iff .
For , the three DFA states are pairwise distinguishable. The empty suffix separates from each rejecting state. Suffix 1 separates from : a prefix ending in 0 becomes accepted, while one with no useful trailing 0 does not. Therefore no two-state DFA can recognize the language.
A nonregularity proof #
Let . Prefixes and with are distinguishable: suffix completes into a member of but does not complete . There are infinitely many distinguishable prefixes, so is not regular.
This proof identifies the missing memory: a finite machine would need to retain an unbounded exact count of preceding zeros.
Minimization is quotienting by observable behavior #
For a complete DFA, remove unreachable states and partition the remaining states into classes that cannot be distinguished by any continuation. A refinement algorithm starts with accepting versus rejecting states and repeatedly splits a block when some input sends its members to different blocks.
The stable blocks are the residual equivalence classes. Merging within each block preserves the language; merging across blocks creates a distinguishing suffix on which behavior changes.
Products give closure and counterexamples #
For complete DFAs and over the same alphabet, their synchronous product has states and transition
After any word , the product is at the pair of component states reached by . That invariant makes several Boolean operations differ only in the accepting predicate:
| Operation | Product pair accepts when… |
|---|---|
| and | |
| or | |
| and | |
| symmetric difference | exactly one of is accepting |
Complement is simpler: flip accepting and rejecting states of a complete deterministic automaton. For a partial diagram, first make every omitted transition explicit by adding a rejecting sink; otherwise a missing run has no state whose acceptance can be flipped.
The product has at most states, but only reachable pairs need be generated. Products, cascade wiring, and decomposition develops this construction in depth.
Decision procedures are graph problems plus invariants #
Once a language is represented by a finite graph, several questions become finite searches:
- Emptiness: is any accepting state reachable from the start?
- Equivalence: is any accepting state reachable in the symmetric-difference product?
- Inclusion: is empty?
- Finiteness: is there a reachable cycle from which an accepting state is reachable?
To explain a failed equivalence check, retain each visited product state's predecessor and incoming symbol. The first reached symmetric-difference state reconstructs a shortest distinguishing word. A Boolean answer becomes a reproducible counterexample.
Formal regex and regex engines are different layers #
The algebra above defines whole languages using union, concatenation, and star. A concrete regex specification also chooses syntax, search scope, and match-selection policy. POSIX, for example, separately specifies Basic and Extended Regular Expressions and a leftmost-longest selection rule.
Other engines may add captures, backreferences, lookaround, or implementation-specific search behavior. Three questions must therefore remain separate:
- Which set of strings does the pattern notation denote?
- If several substrings qualify, which match is selected?
- Which algorithm finds it, and with what performance behavior?
The product name “regex” does not prove that every feature stays within regular-language expressive power.
Diagnostic checklist #
- Did you distinguish , , and ?
- Does a DFA consume the entire word before acceptance is tested?
- For an NFA, did you retain every possible current state rather than choose one branch greedily?
- If epsilon transitions exist, did you close the start and every post-symbol set?
- Does each hand-designed state have a prefix invariant that every outgoing transition preserves?
- In subset construction, are you counting only reachable subsets when describing the actual result?
- Before complement, is the automaton deterministic and complete?
- Are two regular expressions being compared by denotation rather than syntax?
- Can a claimed merge survive every continuation, or is there a distinguishing suffix?
- Is a programming regex claim really about language expressiveness, match selection, or engine execution?
The unifying view is residual behavior: DFA states, determinized NFA subsets, normalized derivatives, and Myhill–Nerode classes all record what continuations remain possible after a prefix. Once that view is internalized, the constructions stop looking like unrelated recipes.