我使用Hashtbl存储(int*string*string)
,这是问题的答案。但是,当我运行答案是不正确的。我认为它正在跳过一些值并且没有计算它们。
这是我的代码:
let solve_memo (x:string) (y:string) : (int*string*string) =
let x_len = String.length x in
let y_len = String.length y in
let tbl_size = x_len * y_len in
let tbl = Hashtbl.create tbl_size in
let case1 xi yi =
if x.[xi] = y.[yi] then 1 else -1
in
let choose_max (pt1,strxi,stryi) (pt2,strx2,stry2) (pt3,strx3,stry3) =
if pt1>pt2 then
if pt1>pt3 then (pt1,strxi,stryi)
else (pt3,strx3,stry3)
else
if pt2>pt3 then (pt2,strx2,stry2)
else (pt3,strx3,stry3)
in
let rec aux xi yi (pt,strx,stry) =
if (xi = x_len && yi = y_len) then (pt,strx,stry)
else
if xi = x_len then
(
pt + (-2 * (y_len - yi)),
String.concat "" [strx; String.make (y_len - yi) ' '],
String.concat "" [stry; String.sub y (yi) (y_len - yi)]
)
else if yi = y_len then
(pt + (-2 * (x_len - xi)),
String.concat "" [strx; String.sub x (xi) (x_len - xi)],
String.concat "" [stry; String.make (x_len - xi) ' ']
)
else
try
Hashtbl.find tbl (xi,yi)
with _ ->
let r1 = aux (xi+1) (yi+1) (pt+(case1 xi yi), String.concat "" [strx; Char.escaped x.[xi]] , String.concat "" [stry; Char.escaped y.[yi]]) in
let r2 = aux (xi+1) yi ((pt-2), String.concat "" [strx; Char.escaped x.[xi]] , String.concat "" [stry; " "]) in
let r3 = aux xi (yi+1) ((pt-2), String.concat "" [strx; " "] , String.concat "" [stry; Char.escaped y.[yi]]) in
let r = choose_max r1 r2 r3 in
let _ = Hashtbl.add tbl (xi,yi) r in
r
in aux 0 0 (0,"","")
;;
当我打印在hashtbl中找到的值时,它会重复2-3次可能在迭代开始时创建的值。 谢谢。
ADD:
这是原始的天真求解函数,我想添加一个Hashtbl来使它更快但它返回错误的结果
let solve (x:string) (y:string) : (int*string*string) =
let x_len = String.length x in
let y_len = String.length y in
let rec aux xi yi (pt,strx,stry) =
let case1 xi yi =
if x.[xi] = y.[yi] then 1 else -1
in
let choose_max (pt1,strxi,stryi) (pt2,strx2,stry2) (pt3,strx3,stry3) =
if pt1>pt2 then
if pt1>pt3 then (pt1,strxi,stryi)
else (pt3,strx3,stry3)
else
if pt2>pt3 then (pt2,strx2,stry2)
else (pt3,strx3,stry3)
in
if xi = x_len then
(
pt + (-2 * (y_len - yi)),
String.concat "" [strx; String.make (y_len - yi) ' '],
String.concat "" [stry; String.sub y (yi) (y_len - yi)]
)
else if yi = y_len then
(pt + (-2 * (String.length x - xi)),
String.concat "" [strx; String.sub x (xi) (x_len - xi)],
String.concat "" [stry; String.make (x_len - xi) ' ']
)
else
let r1 = aux (xi+1) (yi+1) (pt+(case1 xi yi), String.concat "" [strx; Char.escaped x.[xi]] , String.concat "" [stry; Char.escaped y.[yi]]) in
let r2 = aux (xi+1) yi ((pt-2), String.concat "" [strx; Char.escaped x.[xi]] , String.concat "" [stry; " "]) in
let r3 = aux xi (yi+1) ((pt-2), String.concat "" [strx; " "] , String.concat "" [stry; Char.escaped y.[yi]]) in
choose_max r1 r2 r3
in aux 0 0 (0,"","")
;;
答案 0 :(得分:0)
我认为您无法轻松修改此函数以获取用于记忆的hashtbl。这是因为您将累加器(pt,strx,stry)
从三个不同的方向((xi,yi)
.. n0
传递给单元格n2
(累加器表示子序列的对齐),下图)。在与序列的其余部分(r0..r2
)对齐之前,您尚未确定三者中的哪一个是最佳的。
通过添加memoization,你只存储一个这样的调用的结果,而不是最好的。因此,您的结果取决于先前的单元格(来自n0..n2
的累加器)以及对序列其余部分r0..r2
的最佳对齐的恢复。因此,您无法在不详尽的情况下记住结果。要使memoization工作,您需要明确的子问题,而这里没有。