字符串转换的最低成本

时间:2016-10-14 02:13:34

标签: algorithm dynamic-programming

给出两个字符串A和B.我们想将A转换为B.有两种方法可以做到这一点:

  1. 删除N consecutive个字符,每次操作费用为2;
  2. 添加N consecutive个字符(您需要的任何字符),费用为N+2(每个操作)。
  3. 将A转换为B的最低成本是多少? 例如,

    输入

    答:dsafsadfadf

    B:fdfd

    输出

    7

    提示:

    1. dsafsadfadf - > f,删除10个连续字符,cost = 2
    2. f - > fdfd添加3个连续字符(dfd),费用= 3 + 2 = 5
    3. 最低成本= 2 + 5 = 7,小于任何其他转换成本。

      同样,aaaaaaaa - > bbbbbbbb,最低费用= 2 + 10 = 12

      您可以多次使用这两种方式,但不限于2次。

2 个答案:

答案 0 :(得分:1)

这是您可能选择使用的一个递归方向。设f(i,j,n)表示对字符串i的索引A所做的更改的开销,因此当前前缀匹配字符串B直到索引j和之前的更改记录在n中:如果n等于-1,则最后一次更改为删除;如果n为零,则在上一步中没有添加或删除任何字符;如果n为正数,则在最后一步中添加nth个连续字符。复杂性O(|A| * |B|^2)

然后:

var A = "dsafsadfadf",
    B = "fdfd";

function f(i,j,n){ 
  // base case end of A and B
  if (i == A.length && j == B.length){
    return 2 + (n > 0 ? n : 0);
  }  

  // base case end of A:
  if (i == A.length){
    var to_add = B.length - j;
    return 2 + to_add + (n > 0 ? n : 0) + (n < 0 ? 2 : 0);
  }   

  // base case end of B
  if (j == B.length){
    if (n <= 0){
      return 2;
    } else {
      return 4 + n;
    }
  } 

  // otherwise if there's a match
  var use_match = Infinity;

  if (A[i] == B[j]){
    prev_cost = (n != 0 ? 2 : 0) + (n > 0 ? n : 0);
    use_match = prev_cost + f(i + 1,j + 1,0);
  }

  // use or do not use the match
  var delete_char, add_char;

  if (n < 0){
    delete_char = f(i + 1,j,-1);
    add_char = 2 + f(i,j + 1,1);

  } else if (n > 0){
    delete_char = 2 + n + f(i + 1,j,-1);
    add_char = f(i,j + 1,n + 1);

  } else {
    delete_char = f(i + 1,j,-1);
    add_char = f(i,j + 1,1);
  }

  return Math.min(use_match,Math.min(delete_char,add_char));
}

console.log(f(0,0,0));

答案 1 :(得分:1)

这看起来像是经典编辑距离(Levenhstein距离)问题的变体,可以通过类似的动态编程方法来解决。

让函数为f (x, y) =最低成本,将x的{​​{1}}个字符转换为A的前y个字符。考虑一个导致B的这个值的解决方案。什么可能是最后的操作?

可能是从第一个参数的后缀中删除了一些字符,因此对于ff (x, y)的所有f (u, y) + 2u可以是0,包容。

也可能是在第二个参数的后缀中添加了一些字符,因此从xf (x, y)的所有f (x, v) + 2 + (y - v) v可以是0 ,包容性。

现在,请使用上面列出的y选项中的最小值,并获得x + y + 2的值。

基本案例是f (x, y)。 答案是f (0, 0) = 0的价值。

总复杂度类似于O(| A | * | B | *(| A | + | B |))。