动态编程表 - 查找打破字符串的最小成本

时间:2017-08-29 16:11:01

标签: string algorithm dynamic-programming

  

某种字符串处理语言提供原始操作   它将一个字符串分成两部分。由于此操作涉及   复制原始字符串,它需要n个单位的时间用于字符串   长度n,无论切割的位置如何。假设,现在,那   你想把一个字符串分成许多部分。

     

休息的顺序会影响总的运行   时间。例如,假设我们希望打破一个20个字符的字符串(for   示例" abcdefghijklmnopqrst")在索引3,8和   10获得子串:" abcd"," efghi"," jk"和" lmnopqrst"。如果   休息是按照从左到右的顺序进行的,然后第一次休息就是20   单位时间,第二次破发需要16个单位的时间和第三个   打破成本11个单位的时间,总共47个步骤。如果休息   按左右顺序排列,第一次破坏需要20个单位的时间,   第二次休息时间为11个单位,第三次休息时间为9次   单位时间,总共只有40步。但是,最优   解是38(并且切割的顺序是10,3,8)。

输入是字符串的长度和带有剪切索引的升序排序数组。我需要设计一个动态编程表来查找打破字符串的最小成本以及执行剪切的顺序。

我无法弄清楚表格结构的外观(某些单元格应该是某些子问题的答案,应该可以从其他条目等计算出来)。相反,我编写了一个递归函数来查找打破字符串的最小成本:b0, b1, ..., bK是必须对ij之间的(子)字符串进行剪切的索引。 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.

{{1}}

请帮我弄清楚桌子的结构,谢谢!

1 个答案:

答案 0 :(得分:0)

例如,我们有一个长度为n = 20的字符串,我们需要在位置cuts = [3, 8, 10]中将其分解。首先,让我们为我们的数组添加两个假剪切:-1n - 1(以避免边缘情况),现在我们有cuts = [-1, 3, 8, 10, 19]。让我们填写表格M,其中M[i, j]是在i - 和j - 切割之间进行所有休息的最小时间单位。我们可以按规则填写:M[i, j] = (cuts[j] - cuts[i]) + min(M[i, k] + M[k, j]) where i < k < j。进行所有切割的最短时间将在单元格M[0, len(cuts) - 1]中。 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 xrange(cuts_num):
    table += [[0] * cuts_num]
# fill table
for diff in xrange(2, cuts_num):
    for start in xrange(0, cuts_num - diff):
        end = start + diff
        table[start][end] = 1e9
        for mid in xrange(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]