DFA Design: Strings over with at least three occurrences of the substring (overlap allowed)
We want a deterministic finite automaton (DFA) over the alphabet that accepts exactly the strings containing at least three occurrences of the substring , where occurrences may overlap. For example, contains occurrences at positions , , and , so it must be accepted.
A robust way to build such a DFA is to track:
- How much of the current suffix could still be part of a future (i.e., the last symbols of a potential ending),
- How many occurrences have already been completed,
- And to increment the count whenever the transition produces a completed .
We will use the standard “prefix-suffix” memory for the pattern , i.e., track the longest suffix of the processed input that is also a prefix of .
Key concepts:
- Deterministic finite automaton (DFA)
- Substring occurrence
- Overlapping occurrences
- Prefix of a pattern
Mermaid view of the idea:
DFA Design for Substring Matching (automaton intuition)
Formal target language
Let . Define the set of strings
We can formalize an “occurrence” as: occurs starting at position if the length-3 factor .
To handle overlap, we must ensure that after reading a symbol that completes one occurrence, the automaton continues tracking suffixes that may begin another occurrence immediately.
State design strategy (suffix memory + count)
The pattern is . Its prefixes are:
- length :
- length :
- length :
- length : (a completion)
Let the DFA state be a pair:
- count
- suffix
We only need suffix lengths explicitly; suffix length is handled by “increment count then fall back to the appropriate suffix” (because overlaps are allowed).
We cap the count at : once we’ve seen occurrences, we stay in an accepting “done” region.
Suffix transitions for the pattern when reading symbols
Let suffix memory mean:
- : suffix is “nothing useful” (no trailing prefix)
- : suffix is
- : suffix is
Now compute updates on reading next symbol:
-
Reading always breaks any run of :
- from any : suffix becomes (because suffix cannot end in ).
-
Reading extends a run:
- from (“no trailing b-prefix”) reading gives suffix (“ends with ”)
- from reading gives suffix (“ends with ”)
- from reading completes one occurrence:
- count increments
- after consuming that , the new suffix that can start another due to overlap is the suffix (because the last two symbols are )
That last step is the overlap mechanism: in a run of ’s, consecutive windows share characters.
[CalloutBlock] type="tip" title="Pro Tip" content="When overlaps are allowed, don’t reset to 0 after finding a match. Instead, compute the longest suffix that is also a prefix of the pattern (here, after matching the remaining suffix is )."
Construct the DFA (complete transition table)
- 1Step 1
Use states where counts completed occurrences (cap at 3) and is suffix memory for possible -prefix length. Total states: .
- 2Step 2
Start at (no occurrences yet; no relevant trailing ).
- 3Step 3
Accept all states with , i.e., .
- 4Step 4
For any and any , reading sends the DFA to because breaks any trailing run.
- 5Step 5
If then reading sends . If then .
- 6Step 6
If then reading completes one : where is capped at 3, i.e., and .
Complete DFA specification
State set
Let
Start state:
Accepting states:
Transition function
For any :
- On input :
- On input :
- If :
- If :
- If (completion):
This DFA is deterministic because for each state and each symbol , exactly one next state is defined.
[CalloutBlock] type="warning" title="Warning: counting overlaps correctly" content="The only time the count increases is when and the next symbol is . This correctly counts overlapping windows (e.g., adds three matches)."
Transition table (compact)
Let denote .
| Current state | on a | on b |
|---|---|---|
where and .
Example runs (to validate overlap)
Example:
Track :
- Start
- read :
- read :
- read : (first completed)
- read : (second completed, overlapping)
- read : (third completed)
Since , the string is accepted.
Example: idea
Any time an appears, resets to 0, which prevents from completing across the .
State diagram (pattern counter “layered by count”)
Below is a structural view: from each count layer, reading advances suffix memory; hitting and reading moves to the next count layer while staying at .
How count increases in a long run of b’s
In a string of b’s, the number of overlapping occurrences is (for ). The DFA acceptance threshold is at least 3 occurrences.
FAQ and edge cases
DFA Design Flashcards: bbb occurrence counter
Knowledge Check
In the constructed DFA, in which situation does the automaton increase the completed-occurrence count?