Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -0,0 +1,21 @@
|
|||
lcs←{
|
||||
⎕IO←0
|
||||
betterof←{⊃(</+/¨⍺ ⍵)⌽⍺ ⍵} ⍝ better of 2 selections
|
||||
cmbn←{↑,⊃∘.,/(⊂⊂⍬),⍵} ⍝ combine lists
|
||||
rr←{∧/↑>/1 ¯1↓[1]¨⊂⍵} ⍝ rising rows
|
||||
hmrr←{∨/(rr ⍵)∧∧/⍵=⌈\⍵} ⍝ has monotonically rising rows
|
||||
rnbc←{{⍵/⍳⍴⍵}¨↓[0]×⍵} ⍝ row numbers by column
|
||||
valid←hmrr∘cmbn∘rnbc ⍝ any valid solutions?
|
||||
a w←(</⊃∘⍴¨⍺ ⍵)⌽⍺ ⍵ ⍝ longest first
|
||||
matches←a∘.=w
|
||||
aps←{⍵[;⍒+⌿⍵]}∘{(⍵/2)⊤⍳2*⍵} ⍝ all possible subsequences
|
||||
swps←{⍵/⍨∧⌿~(~∨⌿⍺)⌿⍵} ⍝ subsequences with possible solns
|
||||
sstt←matches swps aps⊃⍴w ⍝ subsequences to try
|
||||
w/⍨{
|
||||
⍺←0⍴⍨⊃⍴⍵ ⍝ initial selection
|
||||
(+/⍺)≥+/⍵[;0]:⍺ ⍝ no scope to improve
|
||||
this←⍺ betterof{⍵×valid ⍵/matches}⍵[;0] ⍝ try to improve
|
||||
1=1⊃⍴⍵:this ⍝ nothing left to try
|
||||
this ∇ 1↓[1]⍵ ⍝ keep looking
|
||||
}sstt
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <memory> // for shared_ptr<>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <algorithm> // for lower_bound()
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LCS {
|
||||
protected:
|
||||
// This linked list class is used to trace the LCS candidates
|
||||
class Pair {
|
||||
public:
|
||||
uint32_t index1;
|
||||
uint32_t index2;
|
||||
shared_ptr<Pair> next;
|
||||
|
||||
Pair(uint32_t index1, uint32_t index2, shared_ptr<Pair> next = nullptr)
|
||||
: index1(index1), index2(index2), next(next) {
|
||||
}
|
||||
|
||||
static shared_ptr<Pair> Reverse(const shared_ptr<Pair> pairs) {
|
||||
shared_ptr<Pair> head = nullptr;
|
||||
for (auto next = pairs; next != nullptr; next = next->next)
|
||||
head = make_shared<Pair>(next->index1, next->index2, head);
|
||||
return head;
|
||||
}
|
||||
};
|
||||
|
||||
typedef deque<shared_ptr<Pair>> PAIRS;
|
||||
typedef deque<uint32_t> THRESHOLD;
|
||||
typedef deque<uint32_t> INDEXES;
|
||||
typedef map<char, INDEXES> CHAR2INDEXES;
|
||||
typedef deque<INDEXES*> MATCHES;
|
||||
|
||||
// return the LCS as a linked list of matched index pairs
|
||||
uint64_t LCS::Pairs(MATCHES& matches, shared_ptr<Pair> *pairs) {
|
||||
auto trace = pairs != nullptr;
|
||||
PAIRS traces;
|
||||
THRESHOLD threshold;
|
||||
|
||||
//
|
||||
//[Assert]After each index1 iteration threshold[index3] is the least index2
|
||||
// such that the LCS of s1[0:index1] and s2[0:index2] has length index3 + 1
|
||||
//
|
||||
uint32_t index1 = 0;
|
||||
for (const auto& it1 : matches) {
|
||||
if (!it1->empty()) {
|
||||
auto dq2 = *it1;
|
||||
auto limit = threshold.end();
|
||||
for (auto it2 = dq2.begin(); it2 != dq2.end(); it2++)
|
||||
{
|
||||
// Each of the index1, index2 pairs considered here correspond to a match
|
||||
auto index2 = *it2;
|
||||
//
|
||||
// Note: The index2 values are monotonically decreasing, which allows the
|
||||
// thresholds to be updated in place. Montonicity allows a binary search,
|
||||
// implemented here by std::lower_bound()
|
||||
//
|
||||
limit = lower_bound(threshold.begin(), limit, index2);
|
||||
auto index3 = distance(threshold.begin(), limit);
|
||||
|
||||
//
|
||||
// Look ahead to the next index2 value to optimize space used in the Hunt
|
||||
// and Szymanski algorithm. If the next index2 is also an improvement on
|
||||
// the value currently held in threshold[index3], a new Pair will only be
|
||||
// superseded on the next index2 iteration.
|
||||
//
|
||||
// Depending on match redundancy, the number of Pair constructions may be
|
||||
// divided by factors ranging from 2 up to 10 or more.
|
||||
//
|
||||
auto skip = it2 + 1 != dq2.end() &&
|
||||
(limit == threshold.begin() || *(limit - 1) < *(it2 + 1));
|
||||
|
||||
if (skip) continue;
|
||||
|
||||
if (limit == threshold.end()) {
|
||||
// insert case
|
||||
threshold.push_back(index2);
|
||||
if (trace) {
|
||||
auto prefix = index3 > 0 ? traces[index3 - 1] : nullptr;
|
||||
auto last = make_shared<Pair>(index1, index2, prefix);
|
||||
traces.push_back(last);
|
||||
}
|
||||
}
|
||||
else if (index2 < *limit) {
|
||||
// replacement case
|
||||
*limit = index2;
|
||||
if (trace) {
|
||||
auto prefix = index3 > 0 ? traces[index3 - 1] : nullptr;
|
||||
auto last = make_shared<Pair>(index1, index2, prefix);
|
||||
traces[index3] = last;
|
||||
}
|
||||
}
|
||||
} // next index2
|
||||
}
|
||||
|
||||
index1++;
|
||||
} // next index1
|
||||
|
||||
if (trace) {
|
||||
auto last = traces.size() > 0 ? traces.back() : nullptr;
|
||||
// Reverse longest back-trace
|
||||
*pairs = Pair::Reverse(last);
|
||||
}
|
||||
|
||||
auto length = threshold.size();
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// Match() avoids incurring m*n comparisons by using the associative memory
|
||||
// implemented by CHAR2INDEXES to achieve O(m+n) performance, where m and n
|
||||
// are the input lengths.
|
||||
//
|
||||
// The symbol space is sparse in the case of records; so, the lookup time is
|
||||
// at most O(log(m+n)). The lookup time can be assumed constant in the case
|
||||
// of characters.
|
||||
//
|
||||
void Match(CHAR2INDEXES& indexes, MATCHES& matches,
|
||||
const string& s1, const string& s2) {
|
||||
uint32_t index = 0;
|
||||
for (const auto& it : s2)
|
||||
indexes[it].push_front(index++);
|
||||
|
||||
for (const auto& it : s1) {
|
||||
auto& dq2 = indexes[it];
|
||||
matches.push_back(&dq2);
|
||||
}
|
||||
}
|
||||
|
||||
string Select(shared_ptr<Pair> pairs, uint64_t length,
|
||||
bool right, const string& s1, const string& s2) {
|
||||
string buffer;
|
||||
buffer.reserve(length);
|
||||
for (auto next = pairs; next != nullptr; next = next->next) {
|
||||
auto c = right ? s2[next->index2] : s1[next->index1];
|
||||
buffer.push_back(c);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
string Correspondence(const string& s1, const string& s2) {
|
||||
CHAR2INDEXES indexes;
|
||||
MATCHES matches; // holds references into indexes
|
||||
Match(indexes, matches, s1, s2);
|
||||
shared_ptr<Pair> pairs; // obtain the LCS as index pairs
|
||||
auto length = Pairs(matches, &pairs);
|
||||
return Select(pairs, length, false, s1, s2);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
LCS lcs;
|
||||
auto s = lcs.Correspondence(s1, s2);
|
||||
cout << s << endl;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(defmacro mem-defun (name args body)
|
||||
(let ((hash-name (gensym)))
|
||||
`(let ((,hash-name (make-hash-table :test 'equal)))
|
||||
(defun ,name ,args
|
||||
(or (gethash (list ,@args) ,hash-name)
|
||||
(setf (gethash (list ,@args) ,hash-name)
|
||||
,body))))))
|
||||
|
||||
(mem-defun lcs (xs ys)
|
||||
(labels ((longer (a b) (if (> (length a) (length b)) a b)))
|
||||
(cond ((or (null xs) (null ys)) nil)
|
||||
((equal (car xs) (car ys)) (cons (car xs) (lcs (cdr xs) (cdr ys))))
|
||||
(t (longer (lcs (cdr xs) ys)
|
||||
(lcs xs (cdr ys)))))))
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(coerce (lcs (coerce "thisisatest" 'list) (coerce "testing123testing" 'list)) 'string))))
|
||||
|
||||
"tsitest"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import std.stdio, std.array;
|
||||
|
||||
T[] lcs(T)(in T[] a, in T[] b) pure nothrow {
|
||||
T[] lcs(T)(in T[] a, in T[] b) pure nothrow @safe {
|
||||
if (a.empty || b.empty) return null;
|
||||
if (a[0] == b[0])
|
||||
return a[0] ~ lcs(a[1 .. $], b[1 .. $]);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import std.stdio, std.algorithm, std.range, std.array, std.string,
|
||||
std.typecons;
|
||||
import std.stdio, std.algorithm, std.range, std.array, std.string, std.typecons;
|
||||
|
||||
uint[] lensLCS(R)(R xs, R ys) pure nothrow {
|
||||
uint[] lensLCS(R)(R xs, R ys) pure nothrow @safe {
|
||||
auto prev = new typeof(return)(1 + ys.length);
|
||||
auto curr = new typeof(return)(1 + ys.length);
|
||||
|
||||
|
|
@ -9,9 +8,7 @@ uint[] lensLCS(R)(R xs, R ys) pure nothrow {
|
|||
swap(curr, prev);
|
||||
size_t i = 0;
|
||||
foreach (immutable y; ys) {
|
||||
curr[i + 1] = (x == y)
|
||||
? prev[i] + 1
|
||||
: max(curr[i], prev[i + 1]);
|
||||
curr[i + 1] = (x == y) ? prev[i] + 1 : max(curr[i], prev[i + 1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +17,7 @@ uint[] lensLCS(R)(R xs, R ys) pure nothrow {
|
|||
}
|
||||
|
||||
void calculateLCS(T)(in T[] xs, in T[] ys, bool[] xs_in_lcs,
|
||||
in size_t idx=0) pure nothrow {
|
||||
in size_t idx=0) pure nothrow @safe {
|
||||
immutable nx = xs.length;
|
||||
immutable ny = ys.length;
|
||||
|
||||
|
|
@ -36,33 +33,27 @@ void calculateLCS(T)(in T[] xs, in T[] ys, bool[] xs_in_lcs,
|
|||
const xe = xs[mid .. $];
|
||||
immutable ll_b = lensLCS(xb, ys);
|
||||
|
||||
// retro is slow with dmd.
|
||||
const ll_e = lensLCS(xe.retro, ys.retro);
|
||||
const ll_e = lensLCS(xe.retro, ys.retro); // retro is slow with dmd.
|
||||
|
||||
//immutable k = iota(ny + 1)
|
||||
// .reduce!(max!(j => ll_b[j] + ll_e[ny - j]));
|
||||
immutable k = iota(ny + 1)
|
||||
.minPos!((i,j)=> tuple(ll_b[i] + ll_e[ny-i]) >
|
||||
tuple(ll_b[j] + ll_e[ny-j]))[0];
|
||||
.minPos!((i, j) => tuple(ll_b[i] + ll_e[ny - i]) >
|
||||
tuple(ll_b[j] + ll_e[ny - j]))[0];
|
||||
|
||||
calculateLCS(xb, ys[0 .. k], xs_in_lcs, idx);
|
||||
calculateLCS(xe, ys[k .. $], xs_in_lcs, idx + mid);
|
||||
}
|
||||
}
|
||||
|
||||
const(T)[] lcs(T)(in T[] xs, in T[] ys) pure /*nothrow*/ {
|
||||
const(T)[] lcs(T)(in T[] xs, in T[] ys) pure /*nothrow*/ @safe {
|
||||
auto xs_in_lcs = new bool[xs.length];
|
||||
calculateLCS(xs, ys, xs_in_lcs);
|
||||
|
||||
return zip(xs, xs_in_lcs) // Not nothrow.
|
||||
.filter!q{ a[1] }
|
||||
.map!q{ a[0] }
|
||||
.array;
|
||||
return zip(xs, xs_in_lcs).filter!q{ a[1] }.map!q{ a[0] }.array; // Not nothrow.
|
||||
}
|
||||
|
||||
string lcsString(in string s1, in string s2) pure /*nothrow*/ {
|
||||
//return lcs(s1.representation, s2.representation).assumeChars;
|
||||
return cast(string)lcs(s1.representation, s2.representation);
|
||||
string lcsString(in string s1, in string s2) pure /*nothrow*/ @safe {
|
||||
return lcs(s1.representation, s2.representation).assumeUTF;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
lcs(Xs0, Ys0) ->
|
||||
CacheKey = {lcs_cache, Xs0, Ys0},
|
||||
case get(CacheKey)
|
||||
of undefined ->
|
||||
Result =
|
||||
case {Xs0, Ys0}
|
||||
of {[], _} -> []
|
||||
; {_, []} -> []
|
||||
; {[Same | Xs], [Same | Ys]} ->
|
||||
[Same | lcs(Xs, Ys)]
|
||||
; {[_ | XsRest]=XsAll, [_ | YsRest]=YsAll} ->
|
||||
A = lcs(XsRest, YsAll),
|
||||
B = lcs(XsAll , YsRest),
|
||||
case length(A) > length(B)
|
||||
of true -> A
|
||||
; false -> B
|
||||
end
|
||||
end,
|
||||
undefined = put(CacheKey, Result),
|
||||
Result
|
||||
; Result ->
|
||||
Result
|
||||
end.
|
||||
|
|
@ -1,41 +1,42 @@
|
|||
func lcs(a, b string) string {
|
||||
aLen := len(a)
|
||||
bLen := len(b)
|
||||
lengths := make([][]int, aLen+1)
|
||||
for i := 0; i <= aLen; i++ {
|
||||
lengths[i] = make([]int, bLen+1)
|
||||
}
|
||||
// row 0 and column 0 are initialized to 0 already
|
||||
arunes := []rune(a)
|
||||
brunes := []rune(b)
|
||||
aLen := len(arunes)
|
||||
bLen := len(brunes)
|
||||
lengths := make([][]int, aLen+1)
|
||||
for i := 0; i <= aLen; i++ {
|
||||
lengths[i] = make([]int, bLen+1)
|
||||
}
|
||||
// row 0 and column 0 are initialized to 0 already
|
||||
|
||||
for i := 0; i < aLen; i++ {
|
||||
for j := 0; j < bLen; j++ {
|
||||
if a[i] == b[j] {
|
||||
lengths[i+1][j+1] = lengths[i][j]+1
|
||||
} else if lengths[i+1][j] > lengths[i][j+1] {
|
||||
lengths[i+1][j+1] = lengths[i+1][j]
|
||||
} else {
|
||||
lengths[i+1][j+1] = lengths[i][j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < aLen; i++ {
|
||||
for j := 0; j < bLen; j++ {
|
||||
if arunes[i] == brunes[j] {
|
||||
lengths[i+1][j+1] = lengths[i][j] + 1
|
||||
} else if lengths[i+1][j] > lengths[i][j+1] {
|
||||
lengths[i+1][j+1] = lengths[i+1][j]
|
||||
} else {
|
||||
lengths[i+1][j+1] = lengths[i][j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read the substring out from the matrix
|
||||
s := make([]byte, 0, lengths[aLen][bLen])
|
||||
for x, y := aLen, bLen; x != 0 && y != 0; {
|
||||
if lengths[x][y] == lengths[x-1][y] {
|
||||
x--
|
||||
} else if lengths[x][y] == lengths[x][y-1] {
|
||||
y--
|
||||
} else {
|
||||
s = append(s, a[x-1])
|
||||
x--
|
||||
y--
|
||||
}
|
||||
}
|
||||
// reverse string
|
||||
r := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
r[i] = s[len(s)-1-i]
|
||||
}
|
||||
return string(r)
|
||||
// read the substring out from the matrix
|
||||
s := make([]rune, 0, lengths[aLen][bLen])
|
||||
for x, y := aLen, bLen; x != 0 && y != 0; {
|
||||
if lengths[x][y] == lengths[x-1][y] {
|
||||
x--
|
||||
} else if lengths[x][y] == lengths[x][y-1] {
|
||||
y--
|
||||
} else {
|
||||
s = append(s, arunes[x-1])
|
||||
x--
|
||||
y--
|
||||
}
|
||||
}
|
||||
// reverse string
|
||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
let lcs xs' ys' =
|
||||
let xs = Array.of_list xs'
|
||||
and ys = Array.of_list ys' in
|
||||
let n = Array.length xs
|
||||
and m = Array.length ys in
|
||||
let a = Array.make_matrix (n+1) (m+1) [] in
|
||||
for i = n-1 downto 0 do
|
||||
for j = m-1 downto 0 do
|
||||
a.(i).(j) <- if xs.(i) = ys.(j) then
|
||||
xs.(i) :: a.(i+1).(j+1)
|
||||
else
|
||||
longest a.(i).(j+1) a.(i+1).(j)
|
||||
done
|
||||
done;
|
||||
a.(0).(0)
|
||||
let lcs xs ys =
|
||||
let cache = Hashtbl.create 16 in
|
||||
let rec lcs xs ys =
|
||||
try Hashtbl.find cache (xs, ys) with
|
||||
| Not_found ->
|
||||
let result =
|
||||
match xs, ys with
|
||||
| [], _ -> []
|
||||
| _, [] -> []
|
||||
| x :: xs, y :: ys when x = y ->
|
||||
x :: lcs xs ys
|
||||
| _ :: xs_rest, _ :: ys_rest ->
|
||||
let a = lcs xs_rest ys in
|
||||
let b = lcs xs ys_rest in
|
||||
if (List.length a) > (List.length b) then a else b
|
||||
in
|
||||
Hashtbl.add cache (xs, ys) result;
|
||||
result
|
||||
in
|
||||
lcs xs ys
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
let list_of_string str =
|
||||
let result = ref [] in
|
||||
String.iter (fun x -> result := x :: !result)
|
||||
str;
|
||||
List.rev !result
|
||||
|
||||
let string_of_list lst =
|
||||
let result = String.create (List.length lst) in
|
||||
ignore (List.fold_left (fun i x -> result.[i] <- x; i+1) 0 lst);
|
||||
result
|
||||
let lcs xs' ys' =
|
||||
let xs = Array.of_list xs'
|
||||
and ys = Array.of_list ys' in
|
||||
let n = Array.length xs
|
||||
and m = Array.length ys in
|
||||
let a = Array.make_matrix (n+1) (m+1) [] in
|
||||
for i = n-1 downto 0 do
|
||||
for j = m-1 downto 0 do
|
||||
a.(i).(j) <- if xs.(i) = ys.(j) then
|
||||
xs.(i) :: a.(i+1).(j+1)
|
||||
else
|
||||
longest a.(i).(j+1) a.(i+1).(j)
|
||||
done
|
||||
done;
|
||||
a.(0).(0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
let list_of_string str =
|
||||
let result = ref [] in
|
||||
String.iter (fun x -> result := x :: !result)
|
||||
str;
|
||||
List.rev !result
|
||||
|
||||
let string_of_list lst =
|
||||
let result = String.create (List.length lst) in
|
||||
ignore (List.fold_left (fun i x -> result.[i] <- x; i+1) 0 lst);
|
||||
result
|
||||
|
|
@ -3,12 +3,12 @@ irb(main):001:0> lcs('thisisatest', 'testing123testing')
|
|||
=> "tsitest"
|
||||
=end
|
||||
def lcs(xstr, ystr)
|
||||
return "" if xstr.empty? || ystr.empty?
|
||||
return "" if xstr.empty? || ystr.empty?
|
||||
|
||||
x, xs, y, ys = xstr[0..0], xstr[1..-1], ystr[0..0], ystr[1..-1]
|
||||
if x == y
|
||||
x + lcs(xs, ys)
|
||||
else
|
||||
[lcs(xstr, ys), lcs(xs, ystr)].max_by {|x| x.size}
|
||||
end
|
||||
x, xs, y, ys = xstr[0..0], xstr[1..-1], ystr[0..0], ystr[1..-1]
|
||||
if x == y
|
||||
x + lcs(xs, ys)
|
||||
else
|
||||
[lcs(xstr, ys), lcs(xs, ystr)].max_by {|x| x.size}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,22 @@
|
|||
class LcsWalker
|
||||
class LCS
|
||||
SELF, LEFT, UP, DIAG = [0,0], [0,-1], [-1,0], [-1,-1]
|
||||
|
||||
def initialize(matrix); @m, @i, @j = matrix, 0, 0; end
|
||||
def valid?(i=@i, j=@j); i >= 0 && j >= 0; end
|
||||
def match(c, d); @m[@i][@j] = compute_entry(c, d); end
|
||||
def pos(i, j); @i, @j = i, j; end
|
||||
def lookup(x, y); [@i+x, @j+y]; end
|
||||
def initialize(a, b)
|
||||
@m = Array.new(a.length) { Array.new(b.length) }
|
||||
a.each_char.with_index do |x, i|
|
||||
b.each_char.with_index do |y, j|
|
||||
match(x, y, i, j)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def match(c, d, i, j)
|
||||
@i, @j = i, j
|
||||
@m[i][j] = compute_entry(c, d)
|
||||
end
|
||||
|
||||
def lookup(x, y) [@i+x, @j+y] end
|
||||
def valid?(i=@i, j=@j) i >= 0 && j >= 0 end
|
||||
|
||||
def peek(x, y)
|
||||
i, j = lookup(x, y)
|
||||
|
|
@ -17,10 +28,20 @@ class LcsWalker
|
|||
end
|
||||
|
||||
def backtrack
|
||||
Enumerator.new { |y| y << @i+1 if backstep while valid? }
|
||||
@i, @j = @m.length-1, @m[0].length-1
|
||||
y = []
|
||||
y << @i+1 if backstep? while valid?
|
||||
y.reverse
|
||||
end
|
||||
|
||||
def backstep
|
||||
def backtrack2
|
||||
@i, @j = @m.length-1, @m[0].length-1
|
||||
y = []
|
||||
y << @j+1 if backstep? while valid?
|
||||
[backtrack, y.reverse]
|
||||
end
|
||||
|
||||
def backstep?
|
||||
backstep = compute_backstep
|
||||
@i, @j = lookup(*backstep)
|
||||
backstep == DIAG
|
||||
|
|
@ -34,3 +55,13 @@ class LcsWalker
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def lcs(a, b)
|
||||
walker = LCS.new(a, b)
|
||||
walker.backtrack.map{|i| a[i]}.join
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
puts lcs('thisisatest', 'testing123testing')
|
||||
puts lcs("rosettacode", "raisethysword")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,5 +65,4 @@ object LCS extends App {
|
|||
println{val t = elapsed(s = lcsd(p._1,p._2))
|
||||
"lcsd(\""+p._1+"\",\""+p._2+"\") = \""+s+"\" ("+t+" sec)"}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue