HW1 DPV Chapter 6 Solutions
HW1 DPV Chapter 6 Solutions
1
Algorithm 1 Dictionary(S[1 . . . n])
E(0) = TRUE.
for i = 1 to n do
E(i) = FALSE.
for j = 1 to i do
if E(j − 1) = TRUE and dict(sj . . .si ) = TRUE then
E(i) = TRUE
prev(i) = j
end if
end for
end for
return E(n)
To output the partition into words after running the above algorithm we
use the following procedure.
2
[DPV] Problem 6.8 – Longest common substring
Solution:
Here we are doing the longest common substring (LCStr), as opposed
to the longest common subsequence (LCS). First, we need to figure out the
subproblems. This time, we have two sequences instead of one. Therefore, we
look at the longest common substring (LCStr) for a prefix of X with a prefix
of Y . Since it is asking for substring which means that the sequence has
to be continuous, we should define the subproblems so that the last letters
in both strings are included. Notice that the subproblem only makes sense
when the last letters in both strings are the same.
Let us define the subproblem for each i and j as:
3
Algorithm 3 LCStr(x1 , x2 , . . . , xn , y1 , y2 , . . . , ym )
for i = 0 to n do
P (i, 0) = 0.
end for
for j = 0 to m do
P (0, j) = 0.
end for
for i = 1 to n do
for j = 1 to m do
if xi = yj then
P (i, j) = 1 + P (i − 1, j − 1)
else
P (i, j) = 0
end if
end for
end for
return maxi,j {P (i, j)}
4
[DPV] Problem 6.18 – Making change II
Solution: This problem is very similar to the knapsack problem without
repetition that we saw in class.
First of all, let’s identify the subproblems. Since each denomination is
used at most once, consider the situation for xn . There are two cases, either
If either of the two cases is TRUE, then the answer for the original problem is
TRUE, otherwise it is FALSE. These two subproblems can depend further on
some subproblems defined in the same way recursively, namely, a subproblem
considers a prefix of the denominations and some value.
We define a n × v sized table D defined as:
5
Algorithm 4 Coin Changing II
D(0, 0) = TRUE.
for j = 1 to v do
(0, j) = FALSE.
end for
for i = 1 to n do
for j = 0 to v do
if xi ≤ j then
D(i, j) ← D(i − 1, j) ∨ D(i − 1, j − vi )
else
D(i, j) ← D(i − 1, j)
end if
end for
end for
return D(n, v)
6
[DPV] Problem 6.19 – Making change k
Solution:
Note that, the requirement is we need to use k coins and also we have
unlimited supply of each coin. Therefore, in the subproblem, we should be
able to recover how many coins have been used so far.
Let T (v, i) be TRUE or FALSE whether it is possible to make value v
using exactly i coins. This leads to an O(nkV ) time solution.
Alternatively, we can use a 1-dimensional array.
For 0 ≤ v ≤ V , let
The recurrence is
T (v) = min{1 + T (v − xj ) : 1 ≤ j ≤ n, xj ≤ v}
j
Algorithm 5 Coin-k(x1 , x2 , . . . , xn ; V ; k)
T (0) = 0
for i = 1 to V do
T (i) = ∞
for j = 1 to n do
if xj ≤ i and T (i) > 1 + T (i − xj ) then
T (i) = 1 + T (i − xj )
end if
end for
end for
if T (V ) ≤ k then
return TRUE
else
return FALSE
end if
The table is of size O(V ) and each entry takes O(n) time to compute.
Hence the total running time is O(nV ).
7
[DPV] Problem 6.20 – Optimal Binary Search Tree
Solution:
This is similar to the chain matrix multiply problem that we did in class.
Here we have to use substrings instead of prefixes for our subproblem. For
all i, j where 1 ≤ i ≤ j ≤ n, let
C(i, j) = minimum cost for a binary search tree for words pi , pi+1 , . . . , pj .
The base case is when i = j, and then the expected cost is 1 for the search
for word pi , hence C(i, i) = pi . Let’s also set for j < i C(i, j) = 0 since such
a tree will be empty. These entries where i > j will be helpful for simplifying
our recurrence.
To make the recurrence for C(i, j) we need to decide which word to place
at the root. If we place pk at the root then we need to place pi , . . . , pk−1 in
the left-subtree and pk+1 . . . , pj in the right subtree. The expected number
of comparisons involves 3 parts: words pi , . . . , pj all take 1 comparison at
the root , the remaining cost for the left-subtree is C(i, k − 1), and for the
right-subtree it’s C(k + 1, j). Therefore, for i < j we have:
8
Algorithm 6 BST(p1 , p2 , . . . , pn )
for i = 1 to n do
C(i, i) = pi
end for
for i = 1 to n do
for j = 1 to i − 1 do
C(i, j) = 0
end for
end for
for w = 1 to n − 1 do
for i = 1 to n − w do
j =i+w
C(i, j) = ∞
for k = i to j do
cur = (pi + · · · + pj ) + C(i, k − 1) + C(k + 1, j)
if C(i, j) > cur then
C(i, j) = cur
end if
end for
end for
end for
return (C(1, n))
9
[DPV] Problem 6.26 – Alignment
Solution: This is similar to the Longest Common Subsequence (LCS) prob-
lem, not the Longest Common Substring from this homework, and also to
the Edit Distance problem that we did in class, just a bit more complicat-
ed. Let us use a similar way to what we did for edit distance to define the
subproblem. Let
The recurrence then is the best choice among those three cases:
P (i, j) = max{δ(xi , yj )+P (i−1, j−1), δ(xi , −)+P (i−1, j), δ(−, yj )+P (i, j−1)}.
For the base case, we have to be a bit careful, there is no problem with
assigning P (0, 0) = 0. But how about P (0, j) and P (i, 0)? Can they also
be zero? The answer is no, they should not even be the base case and
should follow the recurrence of assigning P (0, 1) = δ(−, y1 ) and generally
P (0, j) = P (0, j − 1) + δ(−, yj ).
The running time is O(nm).
10
Algorithm 7 Alignment(x1 , x2 , . . . , xn , y1 , y2 , . . . , ym )
P (0, 0) = 0.
for i = 1 to n do
P (i, 0) = P (i − 1, 0) + δ(xi , −).
end for
for j = 1 to m do
P (0, j) = P (0, j − 1) + δ(−, yj ).
end for
for i = 1 to n do
for j = 1 to m do
P (i, j) = max{δ(xi , yj ) + P (i − 1, j − 1), δ(xi , −) + P (i −
1, j), δ(−, yj ) + P (i, j − 1)}
end for
end for
return P (n, m)
11