Algorithm Search⌘K

Proofs: Palindrome partition by backtracking

These are the human proofs of Palindrome partition by backtracking, at full length.

Correctness of palindrome partition by backtracking full

This proof shows: correctness.

We prove that PALINDROME-PARTITIONS outputs every palindromic partition of s=s[0..n−1]s = s[0..n-1] exactly one time, in increasing lexicographic order of the sequences of piece lengths, and that it stops. Indices are 0-based and s[i..j]s[i..j] includes both ends.

Lemma 1 (the table). After lines L1 to L4, pal[i][j]\mathrm{pal}[i][j] is true if and only if s[i..j]s[i..j] is a palindrome, for 0≤i≤j≤n−10 \le i \le j \le n - 1, and ends[i]\mathit{ends}[i] is the increasing list of all jj such that s[i..j]s[i..j] is a palindrome.

Proof. By induction on j−ij - i. If j−i≤1j - i \le 1, the string s[i..j]s[i..j] is a palindrome if and only if s[i]=s[j]s[i] = s[j], which is what line L3 computes. If j−i≥2j - i \ge 2, then s[i..j]s[i..j] is a palindrome if and only if s[i]=s[j]s[i] = s[j] and s[i+1..j−1]s[i+1..j-1] is a palindrome, because the mirror pairs of s[i..j]s[i..j] are the pair (i,j)(i, j) and the mirror pairs of s[i+1..j−1]s[i+1..j-1]. The entry pal[i+1][j−1]\mathrm{pal}[i+1][j-1] is in row i+1i + 1, which line L1 fills before row ii, and it is correct by the induction hypothesis since (j−1)−(i+1)<j−i(j-1) - (i+1) < j - i. Line L4 appends jj to ends[i]\mathit{ends}[i] exactly when pal[i][j]\mathrm{pal}[i][j] is true, and line L2 visits jj in increasing order. □\square

Let P(i)\mathcal{P}(i) be the list of the palindromic partitions of the suffix s[i..n−1]s[i..n-1], sorted in increasing lexicographic order of their sequences of piece lengths. So P(n)\mathcal{P}(n) holds one element, the empty partition. For i<ni < n, each partition of s[i..n−1]s[i..n-1] has a unique first piece s[i..j]s[i..j], which is a palindrome, followed by a partition of s[j+1..n−1]s[j+1..n-1]. So by Lemma 1, P(i)\mathcal{P}(i) is the concatenation, over jj in ends[i]\mathit{ends}[i] in increasing order, of the lists "s[i..j]s[i..j] followed by qq" for qq in P(j+1)\mathcal{P}(j+1). Partitions with a shorter first piece come first in the order, and those with the same first piece are ordered by the rest.

Lemma 2 (one frame). Suppose that at some moment the stack is S0S_0 with the frame (i,0)(i, 0) pushed on top, and path\mathit{path} is a list of pieces π\pi whose total length is ii. Then the loop of lines L6 to L11 runs until the stack is S0S_0 again, without reading or changing S0S_0 before that moment. In this time it outputs exactly π\pi followed by qq for each qq in P(i)\mathcal{P}(i), in the order of P(i)\mathcal{P}(i). When the stack is S0S_0 again, path\mathit{path} is π\pi without its last piece if i>0i > 0, and π\pi if i=0i = 0.

Proof. By strong induction on n−in - i.

Case i=ni = n. Line L7 reads the frame (n,0)(n, 0), and line L8 outputs π\pi, which is π\pi followed by the empty partition, the only element of P(n)\mathcal{P}(n). Then it pops the frame and removes the last piece of path\mathit{path} if n>0n > 0.

Case i<ni < n. Let ends[i]=(j0<j1<⋯<jm−1)\mathit{ends}[i] = (j_0 < j_1 < \cdots < j_{m-1}), with m≥1m \ge 1 because s[i..i]s[i..i] is a palindrome. We show by induction on kk that, for 0≤k≤m0 \le k \le m, the loop reaches a state where the top frame is (i,k)(i, k), the stack below it is S0S_0, path=π\mathit{path} = \pi, and the outputs so far are π\pi followed by the elements of P(i)\mathcal{P}(i) with first piece s[i..j0],…,s[i..jk−1]s[i..j_0], \ldots, s[i..j_{k-1}]. For k=0k = 0 this is the given state. If the claim holds for some k<mk < m, then line L8 does not apply since i<ni < n, line L9 does not apply since k<mk < m, and lines L10 and L11 set the top frame to (i,k+1)(i, k + 1), append the piece s[i..jk]s[i..j_k] to path\mathit{path} and push (jk+1,0)(j_k + 1, 0). Now path\mathit{path} is π\pi followed by s[i..jk]s[i..j_k], of total length jk+1j_k + 1, and n−(jk+1)<n−in - (j_k + 1) < n - i. By the induction hypothesis of the lemma, applied with S0S_0 followed by (i,k+1)(i, k+1) in the role of S0S_0, the loop outputs π\pi, then s[i..jk]s[i..j_k], then qq, for each qq in P(jk+1)\mathcal{P}(j_k + 1) in order, and comes back to the top frame (i,k+1)(i, k + 1) with path=π\mathit{path} = \pi, since jk+1>0j_k + 1 > 0 and the last piece is removed. These are the elements of P(i)\mathcal{P}(i) with first piece s[i..jk]s[i..j_k], so the claim holds for k+1k + 1. At k=mk = m, line L9 applies: it pops the frame, so the stack is S0S_0, and it removes the last piece of path\mathit{path} if i>0i > 0. By the decomposition of P(i)\mathcal{P}(i) above, the outputs are π\pi followed by each element of P(i)\mathcal{P}(i), in order. In all these steps only the top frame and the frames above it are read or changed, so S0S_0 is untouched. □\square

Theorem. PALINDROME-PARTITIONS stops, and it outputs each palindromic partition of ss exactly one time, in increasing lexicographic order of the sequences of piece lengths.

Proof. Line L5 makes the stack hold only the frame (0,0)(0, 0) with path\mathit{path} empty, of total length 0. Lemma 2 with S0S_0 empty and i=0i = 0 shows that the loop comes to an empty stack, so it stops at line L6, and the outputs are the elements of P(0)\mathcal{P}(0), the partitions of ss, each one time and in order. For n=0n = 0 the output is the single empty partition. Each step of the loop either pushes a frame for a new partial partition or pops a frame, and Lemma 2 shows that each pushed frame is popped; the number of partial partitions is finite, so the number of steps is finite. ■\blacksquare

Back to Palindrome partition by backtracking