Definition · BorderA string b is a border of a string s if b is both a prefix and a suffix of s and b is shorter than s. The empty string is a border of every non-empty string, so the set of borders is never empty and “the longest border” is always defined.
Definition · The failure functionFor a pattern p of length m, the failure function is the array fail[0..m] in which fail[k] is the length of the longest border of the prefix p[0..k−1]. By convention fail[0] is treated as before the start and fail[1] = 0, since a single character has only the empty border.
Example · Seven prefixes of ababacaThe prefixes are a, ab, aba, abab, ababa, ababac and ababaca, and their longest borders are the empty string, the empty string, a, ab, aba, the empty string and a. So fail[1..7] is 0, 0, 1, 2, 3, 0, 1. The rise from 0 to 3 across the middle is the pattern's periodicity; the collapse to 0 at ababac is the c, which occurs nowhere else, so no prefix ending in c can be matched by a prefix starting with a.
The lab's table puts that column beside a second one computed from the definition: for each k, try k − 1, then k − 2, down to 1, and stop at the first length where p[0..j−1] equals p[k−j..k−1] as strings. It is O(m^3) and it is obviously right. The panel reports that the two agree on all 7 prefixes.
Theorem · The slide is safeSuppose the pattern is aligned at text offset i and its first k characters have matched, so t[i..i+k−1] = p[0..k−1], and the comparison at k fails. Then no offset strictly between i and i + k − fail[k] can begin a match, and at offset i + k − fail[k] the first fail[k] characters already agree.
Let j be an offset with i < j < i + k, and suppose a match begins at j. The match's first i + k − j characters lie inside the region already known to equal p[0..k−1], so p[0..i+k−j−1] equals t[j..i+k−1], which equals p[j−i..k−1].
That says p[0..i+k−j−1] is both a prefix of the pattern and a suffix of p[0..k−1], so it is a border of p[0..k−1] of length i + k − j. Since fail[k] is the longest such border, i + k − j ≤ fail[k], which rearranges to j ≥ i + k − fail[k].
So no offset before i + k − fail[k] can start a match, and at that offset the border itself is the fail[k] characters already in place. The matcher therefore sets k to fail[k] and leaves the text pointer where it is.
□
That last clause is the property the previous module leaned on. The text pointer only ever advances, so the number of comparisons that succeed or advance it is at most n; the rest are fallbacks, and the bound 2n follows. The lab prints both, and on the opening text it reports 34 comparisons against a bound of 58.
The fallback chain, and why it is every alignment worth trying
Applying fail repeatedly from m gives 7 → 1 → 0 on this pattern. Each step is the longest border of the one before, and by the theorem above every length in that chain is an alignment at which the pattern could still match while no length outside it can. The chain is short here because ababaca has one short border; on aaaaa it is 5 → 4 → 3 → 2 → 1 → 0, every length there is.
The counts on the text below
The panel searches abababacaba ababacaab ababaca, 29 characters, and finds 3 occurrences at offsets 2, 12 and 22. KMP makes 34 character comparisons and the naive matcher makes 61 on the same input, so KMP is ahead by 27 here. The bound 2n is 58, and the measured 34 sits well under it.
Read those four numbers as four different kinds of statement. 34 is a measurement. 61 is another measurement, of a different algorithm on the same input. 58 is a theorem about KMP on every text of 29 characters. And 27 is the difference between two measurements, which is the one number of the four that does not generalise at all — the sibling lesson “Where the Simple Algorithm Wins” has it at negative 4.
What the second column is protecting against
The linear construction is short enough to look self-evident and subtle enough to be wrong in a way that survives testing: an off-by-one in the fallback gives an array that is correct on most patterns and too small on periodic ones, and a matcher using a too-small fail[] still finds every match, just slowly. The failure mode is invisible in the output and visible only in the count.
So the table compares against the definition on every keystroke, over whatever pattern you type, and prints the number of rows where the two disagree. Type a pattern of your own and watch the count stay at 0; that is the check being exercised rather than merely present.