String matching with a finite automaton
Build a finite automaton for the pattern whose state is how much of the pattern has matched so far; then read the text with one table look-up per character.
Build a finite automaton whose state q means "the first q characters of the pattern have matched so far". On
each text character the automaton moves to the next state with one look-up in the table δ; reaching state m means
the pattern is found.
- Time:
O(n) to match, after O(m³·|Σ|) to build δ here - Space:
O(m·|Σ|) - CLRS, section 32.3
The pattern ababaca and the text abababacaba; the automaton has 8 states and the pattern occurs at shift 2.
def automaton_match(T, P):m = len(P)sigma = sorted(set(P) | set(T)) # the alphabet, in the order of delta's columns# delta[q][a]: the state after reading a in state q = the longest prefix of P that ends P[:q] + a.delta = [[0] * len(sigma) for _ in range(m + 1)]for q in range(m + 1):for j, a in enumerate(sigma):k = min(m, q + 1)while not (P[:q] + a).endswith(P[:k]):k = k - 1delta[q][j] = kq = 0shift = 0 # where P sits under T, for the picturematches = []for i in range(len(T)):q = delta[q][sigma.index(T[i])]shift = i - q + 1if q == m:matches.append(i - m + 1)return matches
Start
The table is still empty.
Local variables
Orange = changed in this step
Call stack
- automaton_match()line 1
Explanation
The idea
Build a finite automaton whose state q means "the first q characters of the pattern have matched so far". On
each text character the automaton moves to the next state with one look-up in the table δ; reaching state m means
the pattern is found.
Building δ
δ(q, a) is the length of the longest prefix of P that is a suffix of P[:q] + a: q + 1 if a is the pattern's
next character, otherwise a smaller state that is still valid. Here it is built the simple textbook way; with KMP's
prefix function it can be built in O(m·|Σ|).
Comparison
Reading the text is exactly one step per character (O(n)), even simpler than KMP; but the table grows large for big
alphabets. KMP is really this automaton keeping only π and computing transitions on the fly.
What to watch in the trace
- The
deltatable: each row is a state and each column a character, in the order of thesigmacard.