给出两个字符串A和B.我们想将A转换为B.有两种方法可以做到这一点:
N consecutive
个字符,每次操作费用为2; N consecutive
个字符(您需要的任何字符),费用为N+2
(每个操作)。 将A转换为B的最低成本是多少? 例如,
输入
答:dsafsadfadf
B:fdfd
输出
7
提示:
dsafsadfadf
- > f
,删除10个连续字符,cost = 2 f
- > fdfd
添加3个连续字符(dfd
),费用= 3 + 2 = 5 最低成本= 2 + 5 = 7,小于任何其他转换成本。
同样,aaaaaaaa
- > bbbbbbbb
,最低费用= 2 + 10 = 12
您可以多次使用这两种方式,但不限于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
的这个值的解决方案。什么可能是最后的操作?
可能是从第一个参数的后缀中删除了一些字符,因此对于f
到f (x, y)
的所有f (u, y) + 2
,u
可以是0
,包容。
也可能是在第二个参数的后缀中添加了一些字符,因此从x
到f (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 |))。