Finite Automata
Understand the formal 5-tuple model that describes any finite-state machine, learn how a machine processes an input string, and see why finite automata are the computational model behind every lexer.
What is a Finite Automaton?
A finite automaton (FA) is an abstract machine that:
- Has a finite number of states.
- Reads an input string one symbol at a time, left to right.
- At each step, moves from its current state to a new state based on the current symbol.
- After reading the entire input, it either accepts the string (if it ended in an accepting state) or rejects it.
Finite automata are the mathematical model behind lexical analysers. Every token pattern described by a regular expression can be recognised by a finite automaton.
Informal Example — A Turnstile
Imagine a subway turnstile. It has two states: Locked and Unlocked.
This turnstile is a finite automaton with:
- States: {Locked, Unlocked}
- Input symbols (alphabet): {P, C}
- Transitions: as shown above
- Start state: Locked
- (There's no accepting state here — this is a Moore machine, but the concept is identical)
Formal Definition — The 5-Tuple
A finite automaton is formally defined as a 5-tuple:
| Component | Symbol | Meaning |
|---|---|---|
| States | Q | A finite, non-empty set of states |
| Alphabet | Σ | A finite set of input symbols |
| Transition function | δ | The "rules" for moving between states |
| Start state | q₀ | The state the machine begins in (q₀ ∈ Q) |
| Accepting states | F | A subset of Q; if the machine ends here it accepts (F ⊆ Q) |
Two Types of Finite Automata
| Type | Transitions | ε-moves |
|---|---|---|
| DFA (Deterministic) | Exactly one target per (state, symbol) | Not allowed |
| NFA (Non-deterministic) | Zero, one, or many targets per (state, symbol) | Allowed |
Both accept exactly the same class of languages — the regular languages. NFAs are easier to design; DFAs are easier to implement. The next two topics cover each in detail.
State Diagrams
Finite automata are typically drawn as state transition diagrams:
- Circles represent states.
- Double circles represent accepting (final) states.
- Arrows represent transitions, labelled with the input symbol.
- A filled arrow (→) points to the start state.
Diagram Conventions
Example — Automaton Accepting Strings Ending in 'a'
Language: all strings over {a, b} that end with the character 'a'. Examples of accepted strings: a, ba, aa, bba, aba, bbba, …
Reading the diagram:
- q0 = start state, "have not just seen 'a'"
- q1 = accepting state, "most recent symbol was 'a'"
- On reading 'a' from q0 → move to q1 (we just saw 'a')
- On reading 'b' from q0 → stay in q0 (still haven't ended with 'a')
- On reading 'a' from q1 → stay in q1 (still ending with 'a')
- On reading 'b' from q1 → go back to q0 (the 'a' is no longer the last symbol)
Trace on "bba":
Trace on "ab":
Accepting and Rejecting Strings
Given a finite automaton M = (Q, Σ, δ, q₀, F) and an input string w = a₁a₂…aₙ:
Acceptance Definition
If all three conditions hold, the machine accepts the string. If any condition fails — especially if rₙ ∉ F — the machine rejects the string.
Extended Transition Function δ*
For convenience, we define δ* (delta-star) as the extended transition function that takes a state and an entire string (not just one symbol):
With this, we can write the acceptance condition compactly:
Language of a Finite Automaton
The set of all strings that automaton M accepts is called the language of M, written L(M):
Key theorem (Kleene): A language L is regular (described by a regular expression) if and only if some finite automaton M recognises it, i.e., L = L(M).
Transition Table Representation
A transition table is a tabular alternative to the state diagram — especially useful for larger automata.
Example — Automaton for Strings Ending in 'a'
Notation:
- → marks the start state
- ***** marks accepting states
- Rows = states, Columns = input symbols
- Cell = the target state after the transition
Reading the table:
- Row q0, column a → q1 (matches the diagram arrow q0 --a--> q1)
- Row q0, column b → q0 (loop on q0 with b)
- Row q1, column a → q1 (loop on q1 with a)
- Row q1, column b → q0 (go back to q0)