LCS, edit distance, knapsack and matrix chain
The four classic dynamic programs of the syllabus: longest common subsequence, edit distance, 0/1 knapsack and matrix chain multiplication. For each: the state, the recurrence, the table filled step by step, how to recover the solution, the running time and space, and the standard facts GATE asks (table sizes, pseudo-polynomial time, Catalan number of parenthesisations).
Why it exists
Four problems appear again and again in exams on dynamic programming, and between them they contain every idea a DP question uses: a two-index table over prefixes (LCS, edit distance), a table indexed by a capacity (knapsack), and a table indexed by intervals filled by increasing length (matrix chain). For each GATE asks you to write or read the recurrence, fill a small table, state the time and space, and recognise the traps (pseudo-polynomial time, the number of parenthesisations).
Prerequisites
You need the recipe of dynamic programming: state, recurrence, filling order, answer (dynamic programming).
Precise definitions
Subsequence. A string obtained by deleting zero or more letters, keeping the order ( is a subsequence of ). Not necessarily contiguous (a substring is).
Longest common subsequence (LCS). The longest string that is a subsequence of both and .
Edit distance (Levenshtein). The fewest operations that turn into , where an operation is the insertion of a letter, the deletion of a letter, or the replacement of a letter by another (each costing ).
0/1 knapsack. Items with weights and values (integers), capacity ; choose a subset of total weight at most with maximum total value. Each item is taken or left.
Matrix chain multiplication. Multiply , where is . The product does not depend on the bracketing, but the cost does: multiplying a matrix by a matrix costs scalar multiplications. Find the bracketing with the fewest scalar multiplications (the order of the matrices is fixed, only the brackets are chosen).
How it works
Longest common subsequence
Let be the length of an LCS of the first letters of and the first letters of . Look at the last letters and :
If the letters are equal they can be matched at the end of an LCS (and matching them is never worse); if not, at least one of them is not used. Time and space : entries, each. To find the string, walk back from : if the letters are equal output the letter and go diagonally up-left; otherwise go to the larger of the neighbours above and to the left. If only the length is needed, two rows suffice: space .
Edit distance
Let be the edit distance from the first letters of to the first letters of :
The three terms in the minimum are: delete (move up), insert (move left), replace by (move diagonally). Time and space .
The program below computes the LCS of DYNAMIC and DANCING and the edit distance from SPRING to STRONG, and prints both tables.
#include <stdio.h>
#include <string.h>
static int max(int a, int b) { return a > b ? a : b; }
static int min3(int a, int b, int c) { return a < b ? (a < c ? a : c) : (b < c ? b : c); }
int main(void) {
const char *x = "DYNAMIC", *y = "DANCING";
int m = (int)strlen(x), n = (int)strlen(y);
int L[8][8]; /* L[i][j] = length of a longest common subsequence of the first i letters of x and the first j of y */
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0) L[i][j] = 0;
else if (x[i - 1] == y[j - 1]) L[i][j] = L[i - 1][j - 1] + 1;
else L[i][j] = max(L[i - 1][j], L[i][j - 1]);
}
}
char lcs[8];
int len = L[m][n];
lcs[len] = 0;
for (int i = m, j = n, k = len - 1; i > 0 && j > 0;) { /* walk back from the corner */
if (x[i - 1] == y[j - 1]) { lcs[k--] = x[i - 1]; i--; j--; }
else if (L[i - 1][j] >= L[i][j - 1]) i--;
else j--;
}
printf("LCS of %s and %s has length %d: %s\n", x, y, len, lcs);
const char *s = "SPRING", *t = "STRONG";
int p = (int)strlen(s), q = (int)strlen(t);
int D[7][7]; /* D[i][j] = fewest edits turning the first i letters of s into the first j of t */
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) {
if (i == 0) D[i][j] = j;
else if (j == 0) D[i][j] = i;
else if (s[i - 1] == t[j - 1]) D[i][j] = D[i - 1][j - 1];
else D[i][j] = 1 + min3(D[i - 1][j], D[i][j - 1], D[i - 1][j - 1]);
}
}
printf("edit distance from %s to %s is %d\n", s, t, D[p][q]);
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) printf("%2d", L[i][j]);
printf("\n");
}
for (int i = 0; i <= p; i++) {
for (int j = 0; j <= q; j++) printf("%2d", D[i][j]);
printf("\n");
}
return 0;
}LCS of DYNAMIC and DANCING has length 3: DNI
edit distance from SPRING to STRONG is 2
0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1
0 1 1 2 2 2 2 2
0 1 2 2 2 2 2 2
0 1 2 2 2 2 2 2
0 1 2 2 2 3 3 3
0 1 2 2 3 3 3 3
0 1 2 3 4 5 6
1 0 1 2 3 4 5
2 1 1 2 3 4 5
3 2 2 1 2 3 4
4 3 3 2 2 3 4
5 4 4 3 3 2 3
6 5 5 4 4 3 2The LCS has length (the program finds DNI; DAC is another one: the LCS is not unique). The edit distance is : replace by and by . Step through the two tables; in each step the grammar highlights the case of the recurrence that is used and the explanation gives the three numbers compared.
Longest common subsequence of DYNAMIC and DANCING: start
Computed by a script, not typed- 1L[i][j] = 0 if i = 0 or j = 0
- 2x_i = y_j: L[i][j] = L[i-1][j-1] + 1
- 3x_i != y_j: L[i][j] = max(L[i-1][j], L[i][j-1])
| L | 0:- | 1:D | 2:A | 3:N | 4:C | 5:I | 6:N | 7:G |
|---|---|---|---|---|---|---|---|---|
| 0:- | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1:D | 0 | |||||||
| 2:Y | 0 | |||||||
| 3:N | 0 | |||||||
| 4:A | 0 | |||||||
| 5:M | 0 | |||||||
| 6:I | 0 | |||||||
| 7:C | 0 |
Step 0
L[i][j] is the length of the longest common subsequence of the first i letters of DYNAMIC (rows) and the first j letters of DANCING (columns). The first row and column are the base case (0).
Edit distance from SPRING to STRONG: start
Computed by a script, not typed- 1D[i][0] = i and D[0][j] = j
- 2s_i = t_j: D[i][j] = D[i-1][j-1]
- 3s_i != t_j: D[i][j] = 1 + min(D[i-1][j], D[i][j-1], D[i-1][j-1])
| D | 0:- | 1:S | 2:T | 3:R | 4:O | 5:N | 6:G |
|---|---|---|---|---|---|---|---|
| 0:- | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| 1:S | 1 | ||||||
| 2:P | 2 | ||||||
| 3:R | 3 | ||||||
| 4:I | 4 | ||||||
| 5:N | 5 | ||||||
| 6:G | 6 |
Step 0
D[i][j] is the smallest number of single-letter insertions, deletions and replacements that turn the first i letters of SPRING (rows) into the first j letters of STRONG (columns).
Relations. If only insertions and deletions are allowed, the distance is (checked on random strings). The longest palindromic subsequence of a string is the LCS of the string and its reverse.
0/1 knapsack
Let be the best value that can be obtained from the first items with capacity . Item is either left (value ) or, if it fits, taken (value plus the best for the remaining capacity):
Time and space . Capacity is a number: the time is polynomial in its value but exponential in its length in bits, so this is a pseudo-polynomial algorithm (the problem is NP-hard, no polynomial algorithm is known). The table can be reduced to one row of entries by processing the capacities from down to (so that the entry still holds the value of the previous item); space when only the value is needed. The set of items is recovered by walking back: item is taken exactly when .
The table for items and capacity :
0/1 knapsack, capacity 8: start
Computed by a script, not typed- 1K[0][c] = 0
- 2w_i > c: K[i][c] = K[i-1][c]
- 3K[i][c] = max(K[i-1][c], v_i + K[i-1][c-w_i])
| K | c = 0 | c = 1 | c = 2 | c = 3 | c = 4 | c = 5 | c = 6 | c = 7 | c = 8 |
|---|---|---|---|---|---|---|---|---|---|
| 0 items | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| item 1 (w 3, v 30) | |||||||||
| item 2 (w 4, v 50) | |||||||||
| item 3 (w 2, v 15) | |||||||||
| item 4 (w 5, v 60) |
Step 0
K[i][c] is the best value using only the first i items with capacity c. Item weights 3, 4, 2, 5 and values 30, 50, 15, 60.
The best value is (items and , weight ). The greedy rule of the fractional knapsack (best value per weight first, taking whole items) would take item (ratio ), then item (ratio ) and reach only : the greedy rule fails for the 0/1 problem, DP does not (greedy knapsack).
Matrix chain multiplication
The number of ways to bracket matrices is the Catalan number : for (the DP never lists them). Let be the fewest scalar multiplications for . The last multiplication splits the chain after some (): multiply (a matrix) by (a matrix):
The table is filled by increasing chain length , because the entries on the right use shorter chains. There are states and each takes time: time , space ; exactly split points are examined in total. Keeping the best in a second table gives the bracketing.
The program computes the knapsack and the chain .
#include <stdio.h>
static int max(int a, int b) { return a > b ? a : b; }
int main(void) {
/* 0/1 knapsack: items 1..4, capacity 8 */
int w[5] = {0, 3, 4, 2, 5}, v[5] = {0, 30, 50, 15, 60}, W = 8;
int K[5][9]; /* K[i][c] = best value using only the first i items with capacity c */
for (int i = 0; i <= 4; i++) {
for (int c = 0; c <= W; c++) {
if (i == 0) K[i][c] = 0;
else if (w[i] > c) K[i][c] = K[i - 1][c];
else K[i][c] = max(K[i - 1][c], v[i] + K[i - 1][c - w[i]]);
}
}
printf("knapsack: best value %d, items taken:", K[4][W]);
for (int i = 4, c = W; i > 0; i--)
if (K[i][c] != K[i - 1][c]) { printf(" %d", i); c -= w[i]; }
printf("\n");
/* matrix chain: A1 is 5x12, A2 is 12x4, A3 is 4x20, A4 is 20x8, A5 is 8x10 */
int p[6] = {5, 12, 4, 20, 8, 10}, n = 5;
long m[6][6]; /* m[i][j] = fewest scalar multiplications for A_i ... A_j */
int s[6][6]; /* s[i][j] = the best place k to split */
for (int i = 1; i <= n; i++) m[i][i] = 0;
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
m[i][j] = 1L << 40;
for (int k = i; k < j; k++) {
long cost = m[i][k] + m[k + 1][j] + (long)p[i - 1] * p[k] * p[j];
if (cost < m[i][j]) { m[i][j] = cost; s[i][j] = k; }
}
}
}
printf("matrix chain: fewest multiplications %ld\n", m[1][n]);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (j < i) printf("%6s", ".");
else printf("%6ld", m[i][j]);
}
printf("\n");
}
return 0;
}knapsack: best value 90, items taken: 4 1
matrix chain: fewest multiplications 1400
0 240 640 1040 1400
. 0 960 1024 1440
. . 0 640 960
. . . 0 1600
. . . . 0Fewest multiplications for A1 A2 A3 A4 A5: start
Computed by a script, not typed- 1m[i][i] = 0
- 2m[i][j] = min over k of m[i][k] + m[k+1][j] + p(i-1) p(k) p(j)
| m | j = 1 | j = 2 | j = 3 | j = 4 | j = 5 |
|---|---|---|---|---|---|
| i = 1 | 0 | ||||
| i = 2 | 0 | ||||
| i = 3 | 0 | ||||
| i = 4 | 0 | ||||
| i = 5 | 0 |
Step 0
A1 is 5 x 12, A2 is 12 x 4, A3 is 4 x 20, A4 is 20 x 8, A5 is 8 x 10 (so p = 5, 12, 4, 20, 8, 10). m[i][j] is the fewest scalar multiplications to compute the product A_i ... A_j. Chains of length 2 are filled first, then 3, 4 and 5.
The cheapest bracketing is with scalar multiplications; multiplying from left to right, , costs . In the animation the explanation of each cell lists every split point it tries and marks the best one.
Worked examples
EX 1LCS table by hand
Easy, . Row and column are . Row : (), . Row : , . Row : , : , so . The LCS is , length .
EX 2Edit distance in small cases
Easy: replace by : . (empty): delete three letters: , the base case . : (the table). The distance is at least (the length difference) and at most .
EX 3One knapsack cell
Mediumwith item of weight and value : leaving the item gives ; taking it gives . The maximum is , the entry in the table. For the item (weight ) does not fit in capacity , so .
EX 4Why the bracketing matters
Mediumis , is , is . : . : : ten times more, for the same product.
EX 5Typical questions
GATE level(a) Number of entries of the LCS table for strings of lengths and : ; time . (b) Longest palindromic subsequence of : LCS of and is (). (c) Time of the matrix chain DP: ; space ; number of brackets for matrices: . (d) Why is the knapsack DP not polynomial? , and takes only bits to write. (e) How many entries of the matrix-chain table are actually computed (above the diagonal)? .
Cheat box
Cheat box
- LCS: if the letters are equal, else ; time and space; space for the length.
- Edit distance: equal letters: diagonal; otherwise (delete, insert, replace); base , ; .
- 0/1 knapsack: if ; time, pseudo-polynomial; space with one row.
- Matrix chain: ; by increasing length; time, space; bracketings.
- Insert-delete distance ; palindromic subsequence .
Traps and GATE patterns
Connections
Builds on
Across subjects
No cross-subject links yet.
All four use the recipe of dynamic programming. The 0/1 knapsack contrasts with the greedy fractional knapsack (activity selection and fractional knapsack). Sequence DP of the same kind is in LIS and coin change, and the interval-style table (matrix chain) has a cousin in the shortest-path table of Floyd-Warshall.
PYQs
7 previous year questions from your book. I re-solved each one myself (6 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs
Define Rn to be the maximum amount earned by cutting a rod of length n meters into one or more pieces of integer length and selling them. For i > 0, let p[i] denote the selling prices of a rod whose length is i meters. Consider the array of prices : p[1] = 1, p[2] = 5, p[3] = 8, p[4] = 9, p[5] = 10, p[6] = 17, p[7] = 18 Which of the following statements is/are correct about R 7 ?
- (a)R7 cannot be achieved by a solution consisting of three pieces.
- (b)R7 = 19
- (c)R7 = 18
- (d)R7 is achieved by three different solutions.
Assume that multiplying a matrix G 1 of dimension p×q with another matrix G 2 of dimension q × r requires scalar multiplications. Computing the product of matrices G1 G2 G3 ......Gn can be done by parenthesizing in different ways. Define Gi Gi+1 as an explicitly computed pair for a given parenthesization if they are directly multiplied. For example, in the matrix multiplication chain G1 G2 G3 G4 G5 G6 using parenthesization ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank ! (G1(G2G3)) (G4(G5G6)).G2 G3 and G5 G6 are the only explicitly computed pairs. Consider a matrix multiplication chain F1 F2 F3 F4 F5 , where matrices F1 F2 F3 F4 F5 are of dimensions 2 × 25, 25 × 3, 3 × 16, 16 × 1 and 1×1000, respectively.In the parenthesization of F1 F2 F3 F4 F5 that minimizes the total number of scalar multiplications, the explicitly computed pairs is/are:
Consider the weights and values of items listed below. Note that there is only one unit of each item. The task is to pick a subset of these items such that their total weight is no more than 11 Kgs and their total value is maximized. Moreover, no item may be split. The total value of items picked by an optimal algorithm is denoted by Vopt. A greedy algorithm sorts the items by their value-to-weight ratios in descending order and packs them greedily, starting from the first item in the ordered list. The total value of items picked by the greedy algorithm is denoted by Vgreedy. The value of Vopt - Vgreedy is
Let A 1 , A 2 , A 3 , and A 4 be four matrices of dimensions 10 × 5, 5 × 20, 20 × 10, and 10 × 5, respectively. The minimum number of scalar multiplications required to find the product A1A2A3A4 using the basic matrix multiplication method is .
Four matrices M1, M2, M3 and M4 of dimensions pxq, qxr, rxs and sxt respectively can be multiplied is several ways with different number of total scalar multiplications. For example, when multiplied as ((M1 X M2) X (M3 X M4)), the total number of multiplications is pqr + rst + prt. If p = 10, q = 100, r = 20, s = 5 and t = 80, then the number of scalar multiplications needed is: ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
The subset-sum problem is defined as follows.
Given
a
set
of
n
positive
integers,
S={a1,a2,...,an} and positive integer W, is there
a subset of S whose elements sum to W? A
dynamic program for solving this problem uses
a 2-dimensional Boolean array, X, with n rows
and W+1 columns. X[i,j], 1≤i≤n, 0≤j≤W, is
TRUE if and only if there is a subset of
{a1,a2,...,ai }whose elements sum to j.
Which entry of the array X, if TRUE, implies
that there is a subset whose elements sum to W?- (a)X[1,W]
- (b)X[n,0]
- (c)X[n,W]
- (d)X[n-1,n]
The subset-sum problem is defined as follows.
Given a set of n positive integers, S={a1,a2,...,an
} and positive integer W, is there a subset of S
whose elements sum to W? A dynamic program
for solving this problem uses a 2-dimensional
Boolean array, X, with n rows and W+1
columns. X[i,j], 1≤i≤n, 0≤j≤W, is TRUE if and
only if there is a subset of {a1,a2,...,ai }whose
elements sum to j.Which of the following is
valid for 2≤i≤n and ai≤j≤W?- (a)X[i,j]=X[i-1,j]∨X[i,j-ai ]
- (b)X[i,j]=X[i-1,j]∨X[i-1,j-ai ]
- (c)X[i,j]=X[i-1,j]∧X[i,j-ai ]
- (d)X[i,j]=X[i-1,j]∧X[i-1,j-ai ] ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
Self-check
Question 1
What is the edit distance between and , and between and ?
Show answerHide
in both cases: replace by ; delete the .
Question 2
How many scalar multiplications does need if is and is ?
Show answerHide
.
Question 3
What is the time of the knapsack DP for items and capacity , and why is it called pseudo-polynomial?
Show answerHide
; polynomial in the value but exponential in the number of bits needed to write .
Question 4
How many ways are there to bracket a product of matrices?
Show answerHide
.
Revision card
One-screen revision
- LCS: match diagonal , else max(up, left); .
- Edit distance: match diagonal, else min(up, left, diagonal); .
- 0/1 knapsack: ; pseudo-polynomial; greedy fails.
- Matrix chain: split + ; by length; time, space; Catalan bracketings.
References
- ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 15 Dynamic Programming (15.2 matrix-chain multiplication, 15.4 longest common subsequence) and Problem 15-5 (edit distance); Section 34.5.5 (0/1 knapsack, pseudo-polynomial)
- ·Kleinberg and Tardos, Algorithm Design, Chapter 6 (6.4 knapsack, 6.6 sequence alignment)
- ·Dasgupta, Papadimitriou, Vazirani, Algorithms, Chapter 6 (edit distance, knapsack, chain matrix multiplication)
Verification
Every table was compared with an independent computation: the LCS length against the maximum over ALL common subsequences (300 random pairs), the edit distance against a breadth-first search over strings with the three edit operations (120 random pairs), the knapsack against ALL subsets (300 random instances), the matrix chain against ALL parenthesisations (80 random chains, the number of parenthesisations being the Catalan number), and the number of split evaluations against (n^3 - n)/6. The step-by-step animations are the page programs with a print added after each assignment, and their final tables equal the tables printed by the page programs. Also checked: the insert-and-delete-only distance equals m + n - 2 LCS, the longest palindromic subsequence equals the LCS of a string and its reverse, and the greedy value-per-weight rule gives 80 on the page knapsack against the optimum 90. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)