September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -5,7 +5,7 @@
|
|||
#include <deque>
|
||||
#include <map>
|
||||
#include <algorithm> // for lower_bound()
|
||||
#include <iterator> // for prev()
|
||||
#include <iterator> // for next() and prev()
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -55,10 +55,10 @@ protected:
|
|||
// 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()
|
||||
// thresholds to be updated in-place. Monotonicity allows a binary search,
|
||||
// implemented here by std::lower_bound().
|
||||
//
|
||||
limit = lower_bound(threshold.begin(), limit, index2);
|
||||
auto index3 = distance(threshold.begin(), limit);
|
||||
|
|
@ -72,14 +72,14 @@ protected:
|
|||
// 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));
|
||||
|
||||
auto skip = next(it2) != dq2.end() &&
|
||||
(limit == threshold.begin() || *prev(limit) < *next(it2));
|
||||
if (skip) continue;
|
||||
|
||||
if (limit == threshold.end()) {
|
||||
// insert case
|
||||
threshold.push_back(index2);
|
||||
// Refresh limit iterator:
|
||||
limit = prev(threshold.end());
|
||||
if (trace) {
|
||||
auto prefix = index3 > 0 ? traces[index3 - 1] : nullptr;
|
||||
|
|
@ -136,7 +136,7 @@ protected:
|
|||
string Select(shared_ptr<Pair> pairs, uint64_t length,
|
||||
bool right, const string& s1, const string& s2) {
|
||||
string buffer;
|
||||
buffer.reserve(length);
|
||||
buffer.reserve((uint32_t)length);
|
||||
for (auto next = pairs; next != nullptr; next = next->next) {
|
||||
auto c = right ? s2[next->index2] : s1[next->index1];
|
||||
buffer.push_back(c);
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char* lcs(const char *a, const char *b, char *out)
|
||||
{
|
||||
int longest = 0;
|
||||
int match(const char *a, const char *b, int dep) {
|
||||
if (!a || !b) return 0;
|
||||
if (!*a || !*b) {
|
||||
if (dep <= longest) return 0;
|
||||
out[ longest = dep ] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*a == *b)
|
||||
return match(a + 1, b + 1, dep + 1) && (out[dep] = *a);
|
||||
|
||||
return match(a + 1, b + 1, dep) +
|
||||
match(strchr(a, *b), b, dep) +
|
||||
match(a, strchr(b, *a), dep);
|
||||
}
|
||||
|
||||
return match(a, b, 0) ? out : 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[128];
|
||||
printf("%s\n", lcs("thisisatest", "testing123testing", buf));
|
||||
printf("%p\n", lcs("no", "match", buf));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
(defn longest [xs ys] (if (> (count xs) (count ys)) xs ys))
|
||||
|
||||
|
||||
(def lcs
|
||||
(memoize
|
||||
(fn [[x & xs] [y & ys]]
|
||||
(cond
|
||||
(or (= x nil) (= y nil) ) nil
|
||||
(or (= x nil) (= y nil)) nil
|
||||
(= x y) (cons x (lcs xs ys))
|
||||
:else (longest (lcs (cons x xs) ys) (lcs xs (cons y ys)))))))
|
||||
:else (longest (lcs (cons x xs) ys)
|
||||
(lcs xs (cons y ys)))))))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
-module(lcs).
|
||||
|
||||
%% API exports
|
||||
-export([
|
||||
lcs/2
|
||||
]).
|
||||
|
||||
%%====================================================================
|
||||
%% API functions
|
||||
%%====================================================================
|
||||
|
||||
lcs(A, B) ->
|
||||
{LCS, _Cache} = get_lcs(A, B, [], #{}),
|
||||
lists:reverse(LCS).
|
||||
|
||||
%%====================================================================
|
||||
%% Internal functions
|
||||
%%=====================================================
|
||||
|
||||
get_lcs(A, B, Acc, Cache) ->
|
||||
case maps:find({A, B, Acc}, Cache) of
|
||||
{ok, LCS} -> {LCS, Cache};
|
||||
error ->
|
||||
{NewLCS, NewCache} = compute_lcs(A, B, Acc, Cache),
|
||||
{NewLCS, NewCache#{ {A, B, Acc} => NewLCS }}
|
||||
end.
|
||||
|
||||
compute_lcs(A, B, Acc, Cache) when length(A) == 0 orelse length(B) == 0 ->
|
||||
{Acc, Cache};
|
||||
compute_lcs([Token |ATail], [Token |BTail], Acc, Cache) ->
|
||||
get_lcs(ATail, BTail, [Token |Acc], Cache);
|
||||
compute_lcs([_AToken |ATail]=A, [_BToken |BTail]=B, Acc, Cache) ->
|
||||
{LCSA, CacheA} = get_lcs(A, BTail, Acc, Cache),
|
||||
{LCSB, CacheB} = get_lcs(ATail, B, Acc, CacheA),
|
||||
LCS = case length(LCSA) > length(LCSB) of
|
||||
true -> LCSA;
|
||||
false -> LCSB
|
||||
end,
|
||||
{LCS, CacheB}.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
48> lcs:lcs("thisisatest", "testing123testing").
|
||||
"tsitest"
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
longest(a::String, b::String) = length(a) ≥ length(b) ? a : b
|
||||
|
||||
"""
|
||||
julia> lcsrecursive("thisisatest", "testing123testing")
|
||||
"tsitest"
|
||||
"""
|
||||
# Recursive
|
||||
function lcsrecursive(xstr::String, ystr::String)
|
||||
if length(xstr) == 0 || length(ystr) == 0
|
||||
return ""
|
||||
end
|
||||
|
||||
x, xs, y, ys = xstr[1], xstr[2:end], ystr[1], ystr[2:end]
|
||||
if x == y
|
||||
return string(x, lcsrecursive(xs, ys))
|
||||
else
|
||||
return longest(lcsrecursive(xstr, ys), lcsrecursive(xs, ystr))
|
||||
end
|
||||
end
|
||||
|
||||
# Dynamic
|
||||
function lcsdynamic(a::String, b::String)
|
||||
lengths = zeros(Int, length(a) + 1, length(b) + 1)
|
||||
|
||||
# row 0 and column 0 are initialized to 0 already
|
||||
for (i, x) in enumerate(a), (j, y) in enumerate(b)
|
||||
if x == y
|
||||
lengths[i+1, j+1] = lengths[i, j] + 1
|
||||
else
|
||||
lengths[i+1, j+1] = max(lengths[i+1, j], lengths[i, j+1])
|
||||
end
|
||||
end
|
||||
|
||||
# read the substring out from the matrix
|
||||
result = ""
|
||||
x, y = length(a) + 1, length(b) + 1
|
||||
while x > 1 && y > 1
|
||||
if lengths[x, y] == lengths[x-1, y]
|
||||
x -= 1
|
||||
elseif lengths[x, y] == lengths[x, y-1]
|
||||
y -= 1
|
||||
else
|
||||
@assert a[x-1] == b[y-1]
|
||||
result = string(a[x-1], result)
|
||||
x -= 1
|
||||
y -= 1
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
@show lcsrecursive("thisisatest", "testing123testing")
|
||||
@time lcsrecursive("thisisatest", "testing123testing")
|
||||
@show lcsdynamic("thisisatest", "testing123testing")
|
||||
@time lcsdynamic("thisisatest", "testing123testing")
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// version 1.1.2
|
||||
|
||||
fun lcs(x: String, y: String): String {
|
||||
if (x.length == 0 || y.length == 0) return ""
|
||||
val x1 = x.dropLast(1)
|
||||
val y1 = y.dropLast(1)
|
||||
if (x.last() == y.last()) return lcs(x1, y1) + x.last()
|
||||
val x2 = lcs(x, y1)
|
||||
val y2 = lcs(x1, y)
|
||||
return if (x2.length > y2.length) x2 else y2
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val x = "thisisatest"
|
||||
val y = "testing123testing"
|
||||
println(lcs(x, y))
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
function lcs(sequence a, b)
|
||||
sequence res = ""
|
||||
if length(a) and length(b) then
|
||||
if a[$]=b[$] then
|
||||
res = lcs(a[1..-2],b[1..-2])&a[$]
|
||||
else
|
||||
sequence l = lcs(a[1..-2],b),
|
||||
r = lcs(a,b[1..-2])
|
||||
res = iff(length(l)>length(r)?l:r)
|
||||
end if
|
||||
end if
|
||||
return res
|
||||
end function
|
||||
|
||||
constant tests = {{"1234","1224533324"},
|
||||
{"thisisatest","testing123testing"}}
|
||||
for i=1 to length(tests) do
|
||||
string {a,b} = tests[i]
|
||||
?lcs(a,b)
|
||||
end for
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
function LCSLength(sequence X, sequence Y)
|
||||
sequence C = repeat(repeat(0,length(Y)+1),length(X)+1)
|
||||
for i=1 to length(X) do
|
||||
for j=1 to length(Y) do
|
||||
if X[i]=Y[j] then
|
||||
C[i+1][j+1] := C[i][j]+1
|
||||
else
|
||||
C[i+1][j+1] := max(C[i+1][j], C[i][j+1])
|
||||
end if
|
||||
end for
|
||||
end for
|
||||
return C
|
||||
end function
|
||||
|
||||
function backtrack(sequence C, sequence X, sequence Y, integer i, integer j)
|
||||
if i=0 or j=0 then
|
||||
return ""
|
||||
elsif X[i]=Y[j] then
|
||||
return backtrack(C, X, Y, i-1, j-1) & X[i]
|
||||
else
|
||||
if C[i+1][j]>C[i][j+1] then
|
||||
return backtrack(C, X, Y, i, j-1)
|
||||
else
|
||||
return backtrack(C, X, Y, i-1, j)
|
||||
end if
|
||||
end if
|
||||
end function
|
||||
|
||||
function lcs(sequence a, sequence b)
|
||||
return backtrack(LCSLength(a,b),a,b,length(a),length(b))
|
||||
end function
|
||||
|
||||
constant tests = {{"1234","1224533324"},
|
||||
{"thisisatest","testing123testing"}}
|
||||
for i=1 to length(tests) do
|
||||
string {a,b} = tests[i]
|
||||
?lcs(a,b)
|
||||
end for
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
def lcs(a, b)
|
||||
matrix = Array.new(a.length) { Array.new(b.length) }
|
||||
walker = LcsWalker.new(matrix)
|
||||
|
||||
a.each_char.with_index do |x, i|
|
||||
b.each_char.with_index do |y, j|
|
||||
walker.pos(i, j)
|
||||
walker.match(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
walker.pos(a.length-1, b.length-1)
|
||||
walker.backtrack.inject("") { |s, i| s.prepend(a[i]) }
|
||||
end
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
use std::cmp;
|
||||
|
||||
fn lcs(string1: String, string2: String) -> (usize, String){
|
||||
let total_rows = string1.len() + 1;
|
||||
let total_columns = string2.len() + 1;
|
||||
// rust doesn't allow accessing string by index
|
||||
let string1_chars = string1.as_bytes();
|
||||
let string2_chars = string2.as_bytes();
|
||||
|
||||
let mut table = vec![vec![0; total_columns]; total_rows];
|
||||
|
||||
for row in 1..total_rows{
|
||||
for col in 1..total_columns {
|
||||
if string1_chars[row - 1] == string2_chars[col - 1]{
|
||||
table[row][col] = table[row - 1][col - 1] + 1;
|
||||
} else {
|
||||
table[row][col] = cmp::max(table[row][col-1], table[row-1][col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut common_seq = Vec::new();
|
||||
let mut x = total_rows - 1;
|
||||
let mut y = total_columns - 1;
|
||||
|
||||
while x != 0 && y != 0 {
|
||||
// Check element above is equal
|
||||
if table[x][y] == table[x - 1][y] {
|
||||
x = x - 1;
|
||||
}
|
||||
// check element to the left is equal
|
||||
else if table[x][y] == table[x][y - 1] {
|
||||
y = y - 1;
|
||||
}
|
||||
else {
|
||||
// check the two element at the respective x,y position is same
|
||||
assert_eq!(string1_chars[x-1], string2_chars[y-1]);
|
||||
let char = string1_chars[x - 1];
|
||||
common_seq.push(char);
|
||||
x = x - 1;
|
||||
y = y - 1;
|
||||
}
|
||||
}
|
||||
common_seq.reverse();
|
||||
(table[total_rows - 1][total_columns - 1], String::from_utf8(common_seq).unwrap())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let res = lcs("abcdaf".to_string(), "acbcf".to_string());
|
||||
assert_eq!((4 as usize, "abcf".to_string()), res);
|
||||
let res = lcs("thisisatest".to_string(), "testing123testing".to_string());
|
||||
assert_eq!((7 as usize, "tsitest".to_string()), res);
|
||||
// LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.
|
||||
let res = lcs("AGGTAB".to_string(), "GXTXAYB".to_string());
|
||||
assert_eq!((4 as usize, "GTAB".to_string()), res);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import <Utilities/Sequence.sl>;
|
||||
|
||||
lcsBack(a(1), b(1)) :=
|
||||
let
|
||||
aSub := allButLast(a);
|
||||
bSub := allButLast(b);
|
||||
|
||||
x := lcsBack(a, bSub);
|
||||
y := lcsBack(aSub, b);
|
||||
in
|
||||
[] when size(a) = 0 or size(b) = 0
|
||||
else
|
||||
lcsBack(aSub, bSub) ++ [last(a)] when last(a) = last(b)
|
||||
else
|
||||
x when size(x) > size(y)
|
||||
else
|
||||
y;
|
||||
|
||||
main(args(2)) :=
|
||||
lcsBack(args[1], args[2]) when size(args) >=2
|
||||
else
|
||||
lcsBack("thisisatest", "testing123testing");
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
fcn lcs(a,b){
|
||||
if(not a or not b) return("");
|
||||
if (a[0]==b[0]) return(a[0] + self.fcn(a[1,*],b[1,*]));
|
||||
return(fcn(x,y){if(x.len()>y.len())x else y}(lcs(a,b[1,*]),lcs(a[1,*],b)))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue