3.8.2 · D4String Algorithms

Exercises — KMP algorithm — failure function, O(n+m) — full derivation

3,546 words16 min readBack to topic

Before we start, one reminder of the notation we will lean on the whole page:


Level 1 — Recognition

Exercise 1.1 (L1)

Compute the failure function for the string aabaa.

Recall Solution

We fill one index at a time. For each we look at and find the longest string that is both a prefix and a suffix but not the whole thing.

char longest border
0 a a (none) 0
1 a aa a 1
2 b aab (none) — ends in b, no prefix ends in b except whole 0
3 a aaba a 1
4 a aabaa aa 2

Why ? aabaa starts with aa and ends with aa; those match. The next candidate aab is a prefix but the suffix of length 3 is baaaab. So the answer is .

Answer: .

Exercise 1.2 (L1)

For the string aaaa, what is ? What number does climb to?

Recall Solution

Every prefix of aaaa is all a's, and so is every suffix. The longest proper border of a...a (length ) is a...a of length .

0 a 0
1 aa 1
2 aaa 2
3 aaaa 3

Answer: . It climbs by exactly each step because a run of identical characters extends its border every time.


Level 2 — Application

Exercise 2.1 (L2)

Using the failure-function build algorithm, trace the value of (the running border length) when computing for ababa, given so far.

Recall Solution

The algorithm starts each step at . Here , so . We compare with .

  • a, a → they match. So we extend: .
  • Set .

No fallback was needed because the very first comparison matched.

Figure — KMP algorithm — failure function, O(n+m) — full derivation

What the figure shows: the string ababa drawn as boxed cells. The cyan box marks the old border ab sitting as a prefix (cells 0–1); the amber box marks the same ab sitting as a suffix of the previous prefix abab (cells 2–3). The white arrow points at cell 4 (the new a): because it equals a, both the cyan prefix and amber suffix grow by one cell into aba, so jumps from the old to . The picture is the geometric meaning of the single line "".

Answer: .

Exercise 2.2 (L2)

Run the KMP matching loop for aba (so ), ababa. First find for , then list every reported match position.

Recall Solution

Step 1 — build for aba:

0 a 0
1 ab 0
2 aba 1

So , and the pattern length is .

Step 2 — scan the text with starting at :

before action after
0 a 0 match 1
1 b 1 match 2
2 a 2 match → , report start , then 1
3 b 1 match 2
4 a 2 match → , report start , then 1

Answer: matches at positions and (overlapping occurrences of aba in ababa).


Level 3 — Analysis

Exercise 3.1 (L3)

For aabaaab, the fully-built failure function is . Suppose during matching we reach (all 6 chars aabaaa matched, about to check b) and the text char mismatches. Trace the fallback chain until or a re-match becomes possible, and explain what each fallback means geometrically.

Recall Solution

We index by each fallback. Start .

  • . Meaning: the longest border of the matched prefix aabaaa has length (that border is aa). We slide the pattern so its first aa aligns where the text's last aa sat.
  • Now : compare b with the same text char. Suppose it still mismatches. Fall back: .
  • : compare a. Suppose still mismatch. Fall back: .
  • : we stop the while (guard is ). Now we compare once; if it matches, becomes , else stays .

Chain: . Each arrow drops to the length of the next nested border.

Figure — KMP algorithm — failure function, O(n+m) — full derivation

What the figure shows: the matched prefix aabaaa in boxed cells. The two cyan boxes highlight the border aa appearing at the front (cells 0–1) and at the back (cells 4–5) — this is the length-2 border that refers to. The curved amber arrow sweeps the front aa over onto the back aa, which is exactly what "slide the pattern so its first aa lands on the last aa" looks like. The amber text below spells out the whole fallback chain so you can see each drop lands on the length of the next smaller nested border.

Answer: fallback chain from is .

Exercise 3.2 (L3)

The period of a string of length can be read off the failure function as . For abcabcab () whose last failure value is , compute the smallest period and check whether the string is a "full repetition" (i.e. divides ).

Recall Solution

Border length means the longest border of abcabcab is abcab (length 5). The smallest period is That period is abc: shifting the string right by 3 lines it up with itself where the overlap holds. To be a full repetition we need , i.e. ? No — , remainder .

So abcabcab is almost three copies of abc but chopped off: it is abc abc ab. The period is but the string is not a whole number of periods. (Compare with Borders and Periods of Strings.)

Answer: smallest period ; does not divide , so it is not a full repetition.


Level 4 — Synthesis

Exercise 4.1 (L4)

An adversary wants the failure-function build to do the maximum number of fallback steps in a single step. For pattern length , give one concrete worst-case string, trace the long fallback it triggers, and argue why the total fallback work over the whole build is still , not .

Recall Solution

The chosen string: (five a's then a b), length . We commit to this one string for the rest of the exercise.

Why this is the worst case for . As we scan the five leading a's, the border variable climbs as high as it possibly can: up to index , so just before the final character has reached . The last character b matches none of the earlier a's, so it forces to walk all the way back down through every nested border in one step. No length-6 string can push higher than a full run of equal characters does, so no length-6 string can cause a longer single-step fallback.

Trace of the expensive step (, computing , b):

  • . Compare b with a → mismatch. .
  • . b vs a → mismatch. .
  • . b vs a → mismatch. .
  • . b vs a → mismatch. .
  • . b vs a → mismatch, but the while guard now stops us. So .

That single index performed four fallbacks: .

Why the total is still . Track across the entire build, not one index. Two forces act on :

  • The line j += 1 runs at most once per index , so across all indices increases by at most in total (here at most ).
  • Every while fallback step strictly decreases (because ), by at least .
  • always.

A quantity that starts at , rises by at most in total, and never drops below cannot fall more than times in total. So the number of fallback steps summed over the whole build is — even though one index (here ) absorbed almost all of them. This is the potential / accounting method of Amortized Analysis.

Figure — KMP algorithm — failure function, O(n+m) — full derivation

What the figure shows: a line plot of the value of against each algorithm step while building for aaaaab. The cyan line climbs one step at a time (the five +1 extensions on the leading a's), then plunges straight down at the end (the four fallbacks on the final b). The amber dots mark each recorded state. Visually the "area of rise" bounds the "area of fall": because the line can only go up total, it can only come down total — that is the amortized argument as a shape.

Answer: worst-case string aaaaab; it triggers a 4-step fallback at its last character, yet the total fallback count over the whole build is .

Exercise 4.2 (L4)

Show how to reuse KMP's failure function to count, in , the number of occurrences of (length ) in (length ) without storing the whole match list — and explain why the count is correct even for overlapping matches.

Recall Solution

Idea. Run the ordinary matching loop, but keep a single integer counter. Every time reaches we do count += 1, report nothing, and immediately fall back with so the search continues into overlaps.

j = 0; count = 0
for i = 0 .. n-1:
    while j > 0 and T[i] != P[j]:
        j = pi[j-1]
    if T[i] == P[j]:
        j += 1
    if j == m:
        count += 1
        j = pi[m-1]

Why overlaps are counted correctly. After a full match we do not reset . Setting keeps exactly the longest prefix of that is still validly aligned with the text tail. If can overlap itself (like aba in ababa), this preserved overlap lets the next occurrence be found without moving backward.

Cost. The loop is the same amortized matching loop; building is ; total . Storage is a single counter, extra.

Sanity check. For aa (), aaaa (): matches end at → count . Answer: count overlapping occurrences.


Level 5 — Mastery

Exercise 5.1 (L5)

You are given a string of length and its failure array . Design an method to list all border lengths of the whole string (not just the longest), and apply it to abacabaabacaba.

Recall Solution

Key fact. The set of all border lengths of is exactly the chain Why: the longest border has length . The next-shorter border of must be a border of that longest border (borders nest), and the longest border of a length- prefix is stored at . Repeat until we hit . Each step follows one pointer, and the values strictly decrease, so the chain has length : overall .

Apply to abacabaabacaba (). First we actually build for it. The string is a b a c a b a a b a c a b a. Running the standard build gives So the last value is (the longest border of the whole string is aba, length — the string both starts and ends with aba). Now walk the chain of border lengths:

  • (border aba).
  • Next: (border a).
  • Next: → stop.

Chain of border lengths: .

So has borders of length and (plus the trivial empty border): the prefixes aba and a.

Answer: all non-empty border lengths , found by walking .

Exercise 5.2 (L5)

Prove that the smallest period found from the failure function gives the true minimal period, and use it to decide the minimum number of characters you must append to abcabca to make it a whole number of repeats of its smallest period.

Recall Solution

Why is the minimal period. A period means for all valid ; equivalently, has a border of length (the overlapping prefix/suffix). Larger border smaller period. The largest border has length , which therefore corresponds to the smallest period . Any smaller period would force a longer border than , contradicting maximality. Hence is minimal.

Apply to abcabca (). Its longest border is abca (length ): the prefix abca equals the suffix abca. So and Is ? , remainder , so no — it is abc abc a, one and two-thirds copies of abc.

Minimum characters to append. Appending characters does not change the period we are aiming for (, block abc); we just need the total length to be the next multiple of that is . Multiples of : ; the smallest one is . So we append namely the next two characters of the block abc after position ...a, which are b then c, giving abcabca + bc = abcabcabc = abc .

Answer: minimal period ; append characters (bc) to reach the length-9 full repetition abcabcabc.


Active Recall

What is the smallest-period formula from the failure function?
; the string is a full repetition only if .
How do you enumerate all border lengths of ?
Walk the chain .
Why is total fallback work linear over a whole build/scan?
Fallbacks strictly decrease , which only ever rose by total via j += 1; so total decreases total increases.