A certain string-processing language offers a primitive operation which splits a string into two pieces. Since this operation involves copying the original string, it takes n units of time for a string of length n, regardless of the location of the cut. Suppose, now, that you want to break a string into many pieces.
The order in which the breaks are made can affect the total running time. For example, suppose we wish to break a 20-character string (for example "abcdefghijklmnopqrst") after characters at indices 3, 8, and 10 to obtain for substrings: "abcd", "efghi", "jk" and "lmnopqrst". If the breaks are made in left-right order, then the first break costs 20 units of time, the second break costs 16 units of time and the third break costs 11 units of time, for a total of 47 steps. If the breaks are made in right-left order, the first break costs 20 units of time, the second break costs 11 units of time, and the third break costs 9 units of time, for a total of only 40 steps. However, the optimal solution is 38 (and the order of the cuts is 10, 3, 8).
The input is the length of the string and an ascending-sorted array with the cut indexes. I need to design a dynamic programming table to find the minimal cost to break the string and the order in which the cuts should be performed.
I can't figure out how the table structure should look (certain cells should be the answer to certain sub-problems and should be computable from other entries etc.). Instead, I've written a recursive function to find the minimum cost to break the string: b0, b1, ..., bK
are the indexes for the cuts that have to be made to the (sub)string between i
and j
.
totalCost(i, j, {b0, b1, ..., bK}) = j - i + 1 + min {
totalCost(b0 + 1, j, {b1, b2, ..., bK}),
totalCost(i, b1, {b0 }) + totalCost(b1 + 1, j, {b2, b3, ..., bK}),
totalCost(i, b2, {b0, b1 }) + totalCost(b2 + 1, j, {b3, b4, ..., bK}),
....................................................................................
totalCost(i, bK, {b0, b1, ..., b(k - 1)})
} if k + 1 (the number of cuts) > 1,
j - i + 1 otherwise.
Please help me figure out the structure of the table, thanks!
For example we have a string of length n = 20
and we need to break it in positions cuts = [3, 8, 10]
. First of all let's add two fake cuts to our array: -1
and n - 1
(to avoid edge cases), now we have cuts = [-1, 3, 8, 10, 19]
. Let's fill table M
, where M[i, j]
is a minimum units of time to make all breaks between i
-th and j
-th cuts. We can fill it by rule: M[i, j] = (cuts[j] - cuts[i]) + min(M[i, k] + M[k, j]) where i < k < j
. The minimum time to make all cuts will be in the cell M[0, len(cuts) - 1]
. Full code in python:
# input
n = 20
cuts = [3, 8, 10]
# add fake cuts
cuts = [-1] + cuts + [n - 1]
cuts_num = len(cuts)
# init table with zeros
table = []
for i in range(cuts_num):
table += [[0] * cuts_num]
# fill table
for diff in range(2, cuts_num):
for start in range(0, cuts_num - diff):
end = start + diff
table[start][end] = 1e9
for mid in range(start + 1, end):
table[start][end] = min(table[start][end], table[
start][mid] + table[mid][end])
table[start][end] += cuts[end] - cuts[start]
# print result: 38
print(table[0][cuts_num - 1])