字符串切割的动态规划练习

2024-01-01

我一直在研究以下问题book http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf.

某种字符串处理语言提供了将字符串分成两部分的原始操作。由于此操作涉及复制原始字符串,因此无论剪切位置如何,长度为 n 的字符串都需要 n 个单位的时间。现在假设您想将一根绳子分成许多部分。中断的顺序会影响总运行时间。例如,如果要在位置 3 和 10 处剪切 20 个字符的字符串,则在位置 3 处进行第一次剪切的总成本为 20+17=37,而首先进行位置 10 的成本则为 20+ 10=30。

我需要一个动态编程算法,给定 m 次切割,找到将字符串切割成 m+1 块的最小成本。


在我看来,分而治之的方法似乎是解决此类问题的最佳方法。下面是该算法的 Java 实现:

Note:数组m应按升序排序(使用Arrays.sort(m);)

public int findMinCutCost(int[] m, int n) {
   int cost = n * m.length;
   for (int i=0; i<m.length; i++) {
      cost = Math.min(findMinCutCostImpl(m, n, i), cost);
   }
   return cost;
}

private int findMinCutCostImpl(int[] m, int n, int i) {
   if (m.length == 1) return n;
   int cl = 0, cr = 0;
   if (i > 0) {
      cl = Integer.MAX_VALUE;
      int[] ml = Arrays.copyOfRange(m, 0, i);
      int nl = m[i];
      for (int j=0; j<ml.length; j++) {
         cl = Math.min(findMinCutCostImpl(ml, nl, j), cl);
      }
   }
   if (i < m.length - 1) {
      cr = Integer.MAX_VALUE;
      int[] mr = Arrays.copyOfRange(m, i + 1, m.length);
      int nr = n - m[i];
      for (int j=0; j<mr.length; j++) {
         mr[j] = mr[j] - m[i];
      }
      for (int j=0; j<mr.length; j++) {
         cr = Math.min(findMinCutCostImpl(mr, nr, j), cr);
      }
   }
   return n + cl + cr;
}

例如 :

 int n = 20;
 int[] m = new int[] { 10, 3 };

 System.out.println(findMinCutCost(m, n));

会打印30

** Edit **

我已经实现了另外两种方法来回答问题中的问题。

1. 中值割近似

这种方法总是递归地切割最大的块。结果并不总是最好的解决方案,但提供了不可忽略的增益(根据我的测试,增益约为 +100000%),与最佳成本的最小切损差异可以忽略不计。

public int findMinCutCost2(int[] m, int n) {
   if (m.length == 0) return 0;
   if (m.length == 1) return n;
      float half = n/2f;
      int bestIndex = 0;
      for (int i=1; i<m.length; i++) {
         if (Math.abs(half - m[bestIndex]) > Math.abs(half - m[i])) {
            bestIndex = i;
         }
      }
      int cl = 0, cr = 0;
      if (bestIndex > 0) {
         int[] ml = Arrays.copyOfRange(m, 0, bestIndex);
         int nl = m[bestIndex];
         cl = findMinCutCost2(ml, nl);
      }
      if (bestIndex < m.length - 1) {
         int[] mr = Arrays.copyOfRange(m, bestIndex + 1, m.length);
         int nr = n - m[bestIndex];
         for (int j=0; j<mr.length; j++) {
         mr[j] = mr[j] - m[bestIndex];
      }
      cr = findMinCutCost2(mr, nr);
   }
   return n + cl + cr;
}

2. 恒定时间多次切割

代替计算成本最低,只需使用不同的索引和缓冲区。由于此方法在恒定时间内执行,因此它始终返回 n。另外,方法actually将字符串拆分为子字符串。

public int findMinCutCost3(int[] m, int n) {
   char[][] charArr = new char[m.length+1][];
   charArr[0] = new char[m[0]];
   for (int i=0, j=0, k=0; j<n; j++) {
      //charArr[i][k++] = string[j];   // string is the actual string to split
      if (i < m.length && j == m[i]) {
         if (++i >= m.length) {
            charArr[i] = new char[n - m[i-1]];
         } else {
            charArr[i] = new char[m[i] - m[i-1]];
         }
         k=0;
      }
   }
   return n;
}

Note:最后一个方法可以很容易地修改为接受String str论证而不是n并设置n = str.length(),并返回一个String[]数组来自charArr[][].

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

字符串切割的动态规划练习 的相关文章

  • 固定大小集以包含给定集的最大数量

    我有大约 1000 组尺寸 1 4 1 3 3 5 6 4 5 6 7 5 25 42 67 100 是否有可能找到包含最大数量的给定集合的大小为 20 的集合 检查每一个100 80 20 集 效率低下 我不太确定这是 NP 完全的 考虑
  • 快速搜索压缩文本文件

    我需要能够在大量压缩文件 txt 中搜索文本 压缩可能会改变为其他东西 甚至成为专有的 我想避免解压所有文件并压缩 编码 搜索字符串并在压缩文件中搜索 这应该可以通过对所有文件使用相同的码本使用霍夫曼压缩来实现 我不想重新发明轮子 所以 任
  • 我需要一个支持高效随机访问和 O(k) 插入和删除的容器

    我再次尝试问同样的问题question https stackoverflow com questions 3808708 delete parts of a dynamic array and grow other 但我最终提出了一个不同
  • 如何将一组重叠范围划分为不重叠范围?

    假设您有一组范围 0 100 一 0 75 b 95 150 c 120 130 d 显然 这些范围在某些点上重叠 您将如何剖析这些范围以生成不重叠范围的列表 同时保留与其原始范围相关的信息 在本例中为范围后面的字母 例如 运行算法后的上述
  • 找到一系列间隔的最有效分组

    我有一个应用程序 其中有一系列不重叠的固定宽度间隔 每个间隔都有一个给定的键 每个间隔具有相同的宽度 并且可以存在连续的间隔 本质上 我想以最小化单独间隔的数量的方式对间隔和键进行分组 这可以通过合并具有相同键的连续间隔或查找匹配间隔并将它
  • 解释一下从 N 个给定集合中的每一个中给出第 K 个最大数字的示例?

    今天我尝试解决一个Facebook 编程挑战赛 https facebook interviewstreet com recruit challenges 我遇到的挑战是 酒吧问题 可以找到here https github com alo
  • Karasuba算法递归过多

    我正在尝试用 c 实现 Karasuba 乘法算法 但现在我只是想让它在 python 中工作 这是我的代码 def mult x y b m if max x y lt b return x y bm pow b m x0 x bm x1
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • 关于在字典中查找所有有效单词的算法问题

    给定一个字典 只是一个字符串列表 您收到来自外部来源的未知数量的信件 给定字母串 您将如何列出您可以通过这些字母的任意组合组成的所有有效单词 来自字典 因此 如果您收到 applead 你应该找到apple bad pad lead等 我知
  • 如何仅使用单个数组在 JavaScript 中模拟调用堆栈

    我正在看维基百科页面 https en wikipedia org wiki Call stack在调用堆栈上 并尝试理解这个图像 据我所知 哈哈 const memory memory 0 3 top of stack pointer m
  • 带路径压缩算法的加权 Quick-Union

    有一种 带路径压缩的加权快速联合 算法 代码 public class WeightedQU private int id private int iz public WeightedQU int N id new int N iz new
  • 如何有效地找到距给定点最远的点(从一组点中)?

    我正在寻找一种算法或数据结构来解决以下问题 给你一组点 S 然后你会得到另一个点形式的 Q 查询 对于每个查询 找到集合中距离给定点最远的点 集合中最多有 10 5 个点和 10 5 个查询 所有点的坐标都在 0 到 10 5 范围内 我想
  • 计算两点之间的最短路线

    过去几周我一直在开发一款多人 HTML5 游戏 使用nodejs and websockets 我已经被这个问题困扰了一段时间 想象一下 我用数组实现了这个平铺地图 如下所示 1 or 棕色瓷砖 路上有障碍物 玩家无法通过 0 or 绿色瓷
  • 子序列和

    给定一个整数数组 例如 1 2 3 1 查找是否存在总和为0并返回它 例如 1 2 3 or 2 3 1 检查每个子序列是O n 2 这效率太低了 有改进的想法吗 创建一个新数组 其中每个元素等于前一个元素加上该元素的总和 Input 1
  • 需要一种将网络块范围折叠为超集范围列表的算法

    我的数学不及格 我需要一种有效的方法将网络范围缩小为超集 例如如果我输入 IP 范围列表 1 1 1 1至2 2 2 5 1 1 1 2至2 2 2 4 10 5 5 5至155 5 5 5 10 5 5 6至10 5 5 7 我想返回以下
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • 解开 Knuth 的结:如何重构意大利面条式代码?

    这个问题的灵感来自如何将流程图转化为实施 https stackoverflow com questions 36647765它询问如何通过算法消除goto代码中的语句 这answer https stackoverflow com a 3
  • 如何用约束标记一大组“传递群”?

    在 NealB解决方案之后进行编辑 与以下解决方案相比 NealB的解决方案非常非常快任何另一个 https stackoverflow com q 18033115 answers and 提出了关于 添加约束以提高性能 的新问题 Nea
  • 从 1 到 20 亿,像 (23,29) 这样相差 6 的连续素数对的数量

    如何在考虑时间复杂度的情况下从 1 到 20 亿 使用任何编程语言且不使用任何外部库 找到像 23 29 这样相差 6 的连续素数对的数量 尝试过埃拉托色尼筛 但获得连续素数是一个挑战 使用了生成器 但时间复杂度非常高 代码是 def ge
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选

随机推荐