Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
category:
- Recursion
- Memoization
from: http://rosettacode.org/wiki/Longest_common_subsequence

View file

@ -0,0 +1,94 @@
'''Introduction'''
Define a ''subsequence'' to be any output string obtained by deleting zero or more symbols from an input string.
The [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem '''Longest Common Subsequence'''] ('''LCS''') is a subsequence of maximum length common to two or more strings.
Let ''A'' ≡ ''A''[0]… ''A''[m - 1] and ''B'' ≡ ''B''[0]… ''B''[n - 1], m < n be strings drawn from an alphabet Σ of size s, containing every distinct symbol in A + B.
An ordered pair (i, j) will be referred to as a match if ''A''[i] = ''B''[j], where 0 ≤ i < m and 0 ≤ j < n.
The set of matches '''M''' defines a relation over matches: '''M'''[i, j] ⇔ (i, j) ∈ '''M'''.
Define a ''non-strict'' [https://en.wikipedia.org/wiki/Product_order product-order] (≤) over ordered pairs, such that (i1, j1) ≤ (i2, j2) ⇔ i1 ≤ i2 and j1 ≤ j2. We define (≥) similarly.
We say ordered pairs p1 and p2 are ''comparable'' if either p1 ≤ p2 or p1 ≥ p2 holds. If i1 < i2 and j2 < j1 (or i2 < i1 and j1 < j2) then neither p1 ≤ p2 nor p1 ≥ p2 are possible, and we say p1 and p2 are ''incomparable''.
Define the ''strict'' product-order (<) over ordered pairs, such that (i1, j1) < (i2, j2) ⇔ i1 < i2 and j1 < j2. We define (>) similarly.
A chain '''C''' is a subset of '''M''' consisting of at least one element m; and where either m1 < m2 or m1 > m2 for every pair of distinct elements m1 and m2. An antichain '''D''' is any subset of '''M''' in which every pair of distinct elements m1 and m2 are incomparable.
A chain can be visualized as a strictly increasing curve that passes through matches (i, j) in the m*n coordinate space of '''M'''[i, j].
Every Common Sequence of length ''q'' corresponds to a chain of cardinality ''q'', over the set of matches '''M'''. Thus, finding an LCS can be restated as the problem of finding a chain of maximum cardinality ''p''.
According to [Dilworth 1950], this cardinality ''p'' equals the minimum number of disjoint antichains into which '''M''' can be decomposed. Note that such a decomposition into the minimal number p of disjoint antichains may not be unique.
'''Background'''
Where the number of symbols appearing in matches is small relative to the length of the input strings, reuse of the symbols increases; and the number of matches will tend towards O(''m*n'') quadratic growth. This occurs, for example, in the Bioinformatics application of nucleotide and protein sequencing.
The divide-and-conquer approach of [Hirschberg 1975] limits the space required to O(''n''). However, this approach requires O(''m*n'') time even in the best case.
This quadratic time dependency may become prohibitive, given very long input strings. Thus, heuristics are often favored over optimal Dynamic Programming solutions.
In the application of comparing file revisions, records from the input files form a large symbol space; and the number of symbols approaches the length of the LCS. In this case the number of matches reduces to linear, O(''n'') growth.
A binary search optimization due to [Hunt and Szymanski 1977] can be applied to the basic Dynamic Programming approach, resulting in an expected performance of O(''n log m''). Performance can degrade to O(''m*n log m'') time in the worst case, as the number of matches grows to O(''m*n'').
'''Note'''
[Rick 2000] describes a linear-space algorithm with a time bound of O(''n*s + p*min(m, n - p)'').
'''Legend'''
A, B are input strings of lengths m, n respectively
p is the length of the LCS
M is the set of matches (i, j) such that A[i] = B[j]
r is the magnitude of M
s is the magnitude of the alphabet Σ of distinct symbols in A + B
'''References'''
[Dilworth 1950] "A decomposition theorem for partially ordered sets"
by Robert P. Dilworth, published January 1950,
Annals of Mathematics [Volume 51, Number 1, ''pp.'' 161-166]
[Goeman and Clausen 2002] "A New Practical Linear Space Algorithm for the Longest Common
Subsequence Problem" by Heiko Goeman and Michael Clausen,
published 2002, Kybernetika [Volume 38, Issue 1, ''pp.'' 45-66]
[Hirschberg 1975] "A linear space algorithm for computing maximal common subsequences"
by Daniel S. Hirschberg, published June 1975
Communications of the ACM [Volume 18, Number 6, ''pp.'' 341-343]
[Hunt and McIlroy 1976] "An Algorithm for Differential File Comparison"
by James W. Hunt and M. Douglas McIlroy, June 1976
Computing Science Technical Report, Bell Laboratories 41
[Hunt and Szymanski 1977] "A Fast Algorithm for Computing Longest Common Subsequences"
by James W. Hunt and Thomas G. Szymanski, published May 1977
Communications of the ACM [Volume 20, Number 5, ''pp.'' 350-353]
[Rick 2000] "Simple and fast linear space computation of longest common subsequences"
by Claus Rick, received 17 March 2000, Information Processing Letters,
Elsevier Science [Volume 75, ''pp.'' 275281]
<br />
'''Examples'''
The sequences "1234" and "1224533324" have an LCS of "1234":
'''<u>1234</u>'''
'''<u>12</u>'''245'''<u>3</u>'''332'''<u>4</u>'''
For a string example, consider the sequences "thisisatest" and "testing123testing". An LCS would be "tsitest":
'''<u>t</u>'''hi'''<u>si</u>'''sa'''<u>test</u>'''
'''<u>t</u>'''e'''<u>s</u>'''t'''<u>i</u>'''ng123'''<u>test</u>'''ing
In this puzzle, your code only needs to deal with strings. Write a function which returns an LCS of two strings (case-sensitive). You don't need to show multiple LCS's.
For more information on this problem please see [[wp:Longest_common_subsequence_problem|Wikipedia]].
{{Template:Strings}}
<br><br>

View file

@ -0,0 +1,20 @@
F lcs(a, b)
V lengths = [[0] * (b.len+1)] * (a.len+1)
L(x) a
V i = L.index
L(y) b
V j = L.index
I x == y
lengths[i + 1][j + 1] = lengths[i][j] + 1
E
lengths[i + 1][j + 1] = max(lengths[i + 1][j], lengths[i][j + 1])
V result =
V j = b.len
L(i) 1..a.len
I lengths[i][j] != lengths[i - 1][j]
result = a[i - 1]
R result
print(lcs(1234, 1224533324))
print(lcs(thisisatest, testing123testing))

View file

@ -0,0 +1,15 @@
main:(
PROC lcs = (STRING a, b)STRING:
BEGIN
IF UPB a = 0 OR UPB b = 0 THEN
""
ELIF a [UPB a] = b [UPB b] THEN
lcs (a [:UPB a - 1], b [:UPB b - 1]) + a [UPB a]
ELSE
STRING x = lcs (a, b [:UPB b - 1]);
STRING y = lcs (a [:UPB a - 1], b);
IF UPB x > UPB y THEN x ELSE y FI
FI
END # lcs #;
print((lcs ("thisisatest", "testing123testing"), new line))
)

View file

@ -0,0 +1,21 @@
lcs{
⎕IO0
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
validhmrrcmbnrnbc ⍝ any valid solutions?
a w(</¨ ) ⍝ longest first
matchesa.=w
aps{[;+]}{(/2)2*} ⍝ all possible subsequences
swps{/~(~)} ⍝ subsequences with possible solns
ssttmatches swps apsw ⍝ 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
}

View file

@ -0,0 +1,25 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure Test_LCS is
function LCS (A, B : String) return String is
begin
if A'Length = 0 or else B'Length = 0 then
return "";
elsif A (A'Last) = B (B'Last) then
return LCS (A (A'First..A'Last - 1), B (B'First..B'Last - 1)) & A (A'Last);
else
declare
X : String renames LCS (A, B (B'First..B'Last - 1));
Y : String renames LCS (A (A'First..A'Last - 1), B);
begin
if X'Length > Y'Length then
return X;
else
return Y;
end if;
end;
end if;
end LCS;
begin
Put_Line (LCS ("thisisatest", "testing123testing"));
end Test_LCS;

View file

@ -0,0 +1,45 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure Test_LCS is
function LCS (A, B : String) return String is
L : array (A'First..A'Last + 1, B'First..B'Last + 1) of Natural;
begin
for I in L'Range (1) loop
L (I, B'First) := 0;
end loop;
for J in L'Range (2) loop
L (A'First, J) := 0;
end loop;
for I in A'Range loop
for J in B'Range loop
if A (I) = B (J) then
L (I + 1, J + 1) := L (I, J) + 1;
else
L (I + 1, J + 1) := Natural'Max (L (I + 1, J), L (I, J + 1));
end if;
end loop;
end loop;
declare
I : Integer := L'Last (1);
J : Integer := L'Last (2);
R : String (1..Integer'Max (A'Length, B'Length));
K : Integer := R'Last;
begin
while I > L'First (1) and then J > L'First (2) loop
if L (I, J) = L (I - 1, J) then
I := I - 1;
elsif L (I, J) = L (I, J - 1) then
J := J - 1;
else
I := I - 1;
J := J - 1;
R (K) := A (I);
K := K - 1;
end if;
end loop;
return R (K + 1..R'Last);
end;
end LCS;
begin
Put_Line (LCS ("thisisatest", "testing123testing"));
end Test_LCS;

View file

@ -0,0 +1,27 @@
lcs: function [a,b][
ls: new array.of: @[inc size a, inc size b] 0
loop.with:'i a 'x [
loop.with:'j b 'y [
ls\[i+1]\[j+1]: (x=y)? -> ls\[i]\[j] + 1
-> max @[ls\[i+1]\[j], ls\[i]\[j+1]]
]
]
[result, x, y]: @[new "", size a, size b]
while [and? [x > 0][y > 0]][
if? ls\[x]\[y] = ls\[x-1]\[y] -> x: x-1
else [
if? ls\[x]\[y] = ls\[x]\[y-1] -> y: y-1
else [
result: a\[x-1] ++ result
x: x-1
y: y-1
]
]
]
return result
]
print lcs "1234" "1224533324"
print lcs "thisisatest" "testing123testing"

View file

@ -0,0 +1,28 @@
lcs(a,b) { ; Longest Common Subsequence of strings, using Dynamic Programming
Loop % StrLen(a)+2 { ; Initialize
i := A_Index-1
Loop % StrLen(b)+2
j := A_Index-1, len%i%_%j% := 0
}
Loop Parse, a ; scan a
{
i := A_Index, i1 := i+1, x := A_LoopField
Loop Parse, b ; scan b
{
j := A_Index, j1 := j+1, y := A_LoopField
len%i1%_%j1% := x=y ? len%i%_%j% + 1
: (u:=len%i1%_%j%) > (v:=len%i%_%j1%) ? u : v
}
}
x := StrLen(a)+1, y := StrLen(b)+1
While x*y { ; construct solution from lengths
x1 := x-1, y1 := y-1
If (len%x%_%y% = len%x1%_%y%)
x := x1
Else If (len%x%_%y% = len%x%_%y1%)
y := y1
Else
x := x1, y := y1, t := SubStr(a,x,1) t
}
Return t
}

View file

@ -0,0 +1,14 @@
function LCS(a, b)
if length(a) = 0 or length(b) = 0 then return ""
if right(a, 1) = right(b, 1) then
LCS = LCS(left(a, length(a) - 1), left(b, length(b) - 1)) + right(a, 1)
else
x = LCS(a, left(b, length(b) - 1))
y = LCS(left(a, length(a) - 1), b)
if length(x) > length(y) then return x else return y
end if
end function
print LCS("1234", "1224533324")
print LCS("thisisatest", "testing123testing")
end

View file

@ -0,0 +1,12 @@
PRINT FNlcs("1234", "1224533324")
PRINT FNlcs("thisisatest", "testing123testing")
END
DEF FNlcs(a$, b$)
IF a$="" OR b$="" THEN = ""
IF RIGHT$(a$) = RIGHT$(b$) THEN = FNlcs(LEFT$(a$), LEFT$(b$)) + RIGHT$(a$)
LOCAL x$, y$
x$ = FNlcs(a$, LEFT$(b$))
y$ = FNlcs(LEFT$(a$), b$)
IF LEN(y$) > LEN(x$) SWAP x$,y$
= x$

View file

@ -0,0 +1 @@
LCS ¯1 "" < ""¨ (>){𝕩𝔽¨𝔽`𝕨¨""<»𝕩}˝ (=¨)

View file

@ -0,0 +1,4 @@
"1234" LCS "1224533324"
"1234"
"thisisatest" LCS "testing123testing"
"tsitest"

View file

@ -0,0 +1,13 @@
( LCS
= A a ta B b tb prefix
. !arg:(?prefix.@(?A:%?a ?ta).@(?B:%?b ?tb))
& ( !a:!b&LCS$(!prefix !a.!ta.!tb)
| LCS$(!prefix.!A.!tb)&LCS$(!prefix.!ta.!B)
)
| !prefix:? ([>!max:[?max):?lcs
|
)
& 0:?max
& :?lcs
& LCS$(.thisisatest.testing123testing)
& out$(max !max lcs !lcs);

View file

@ -0,0 +1,165 @@
#include <stdint.h>
#include <string>
#include <memory> // for shared_ptr<>
#include <iostream>
#include <deque>
#include <unordered_map> //[C++11]
#include <algorithm> // for lower_bound()
#include <iterator> // for next() and prev()
using namespace std;
class LCS {
protected:
// Instances of the Pair linked list class are used to recover the LCS:
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> INDEXES;
typedef unordered_map<char, INDEXES> CHAR_TO_INDEXES_MAP;
typedef deque<INDEXES*> MATCHES;
static uint32_t FindLCS(
MATCHES& indexesOf2MatchedByIndex1, shared_ptr<Pair>* pairs) {
auto traceLCS = pairs != nullptr;
PAIRS chains;
INDEXES prefixEnd;
//
//[Assert]After each index1 iteration prefixEnd[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 : indexesOf2MatchedByIndex1) {
auto dq2 = *it1;
auto limit = prefixEnd.end();
for (auto it2 = dq2.rbegin(); it2 != dq2.rend(); it2++) {
// Each index1, index2 pair corresponds to a match
auto index2 = *it2;
//
// Note: The reverse iterator it2 visits index2 values in descending order,
// allowing in-place update of prefixEnd[]. std::lower_bound() is used to
// perform a binary search.
//
limit = lower_bound(prefixEnd.begin(), limit, index2);
//
// Look ahead to the next index2 value to optimize Pairs used by the Hunt
// and Szymanski algorithm. If the next index2 is also an improvement on
// the value currently held in prefixEnd[index3], a new Pair will only be
// superseded on the next index2 iteration.
//
// Verify that a next index2 value exists; and that this value is greater
// than the final index2 value of the LCS prefix at prev(limit):
//
auto preferNextIndex2 = next(it2) != dq2.rend() &&
(limit == prefixEnd.begin() || *prev(limit) < *next(it2));
//
// Depending on match redundancy, this optimization may reduce the number
// of Pair allocations by factors ranging from 2 up to 10 or more.
//
if (preferNextIndex2) continue;
auto index3 = distance(prefixEnd.begin(), limit);
if (limit == prefixEnd.end()) {
// Insert Case
prefixEnd.push_back(index2);
// Refresh limit iterator:
limit = prev(prefixEnd.end());
if (traceLCS) {
chains.push_back(pushPair(chains, index3, index1, index2));
}
}
else if (index2 < *limit) {
// Update Case
// Update limit value:
*limit = index2;
if (traceLCS) {
chains[index3] = pushPair(chains, index3, index1, index2);
}
}
} // next index2
index1++;
} // next index1
if (traceLCS) {
// Return the LCS as a linked list of matched index pairs:
auto last = chains.empty() ? nullptr : chains.back();
// Reverse longest chain
*pairs = Pair::Reverse(last);
}
auto length = prefixEnd.size();
return length;
}
private:
static shared_ptr<Pair> pushPair(
PAIRS& chains, const ptrdiff_t& index3, uint32_t& index1, uint32_t& index2) {
auto prefix = index3 > 0 ? chains[index3 - 1] : nullptr;
return make_shared<Pair>(index1, index2, prefix);
}
protected:
//
// Match() avoids m*n comparisons by using CHAR_TO_INDEXES_MAP to
// achieve O(m+n) performance, where m and n are the input lengths.
//
// The lookup time can be assumed constant in the case of characters.
// The symbol space is larger in the case of records; but the lookup
// time will be O(log(m+n)), at most.
//
static void Match(
CHAR_TO_INDEXES_MAP& indexesOf2MatchedByChar, MATCHES& indexesOf2MatchedByIndex1,
const string& s1, const string& s2) {
uint32_t index = 0;
for (const auto& it : s2)
indexesOf2MatchedByChar[it].push_back(index++);
for (const auto& it : s1) {
auto& dq2 = indexesOf2MatchedByChar[it];
indexesOf2MatchedByIndex1.push_back(&dq2);
}
}
static string Select(shared_ptr<Pair> pairs, uint32_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:
static string Correspondence(const string& s1, const string& s2) {
CHAR_TO_INDEXES_MAP indexesOf2MatchedByChar;
MATCHES indexesOf2MatchedByIndex1; // holds references into indexesOf2MatchedByChar
Match(indexesOf2MatchedByChar, indexesOf2MatchedByIndex1, s1, s2);
shared_ptr<Pair> pairs; // obtain the LCS as index pairs
auto length = FindLCS(indexesOf2MatchedByIndex1, &pairs);
return Select(pairs, length, false, s1, s2);
}
};

View file

@ -0,0 +1,2 @@
auto s = LCS::Correspondence(s1, s2);
cout << s << endl;

View file

@ -0,0 +1,33 @@
using System;
namespace LCS
{
class Program
{
static void Main(string[] args)
{
string word1 = "thisisatest";
string word2 = "testing123testing";
Console.WriteLine(lcsBack(word1, word2));
Console.ReadKey();
}
public static string lcsBack(string a, string b)
{
string aSub = a.Substring(0, (a.Length - 1 < 0) ? 0 : a.Length - 1);
string bSub = b.Substring(0, (b.Length - 1 < 0) ? 0 : b.Length - 1);
if (a.Length == 0 || b.Length == 0)
return "";
else if (a[a.Length - 1] == b[b.Length - 1])
return lcsBack(aSub, bSub) + a[a.Length - 1];
else
{
string x = lcsBack(a, bSub);
string y = lcsBack(aSub, b);
return (x.Length > y.Length) ? x : y;
}
}
}
}

View file

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#define MAX(a, b) (a > b ? a : b)
int lcs (char *a, int n, char *b, int m, char **s) {
int i, j, k, t;
int *z = calloc((n + 1) * (m + 1), sizeof (int));
int **c = calloc((n + 1), sizeof (int *));
for (i = 0; i <= n; i++) {
c[i] = &z[i * (m + 1)];
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (a[i - 1] == b[j - 1]) {
c[i][j] = c[i - 1][j - 1] + 1;
}
else {
c[i][j] = MAX(c[i - 1][j], c[i][j - 1]);
}
}
}
t = c[n][m];
*s = malloc(t);
for (i = n, j = m, k = t - 1; k >= 0;) {
if (a[i - 1] == b[j - 1])
(*s)[k] = a[i - 1], i--, j--, k--;
else if (c[i][j - 1] > c[i - 1][j])
j--;
else
i--;
}
free(c);
free(z);
return t;
}

View file

@ -0,0 +1,10 @@
int main () {
char a[] = "thisisatest";
char b[] = "testing123testing";
int n = sizeof a - 1;
int m = sizeof b - 1;
char *s = NULL;
int t = lcs(a, n, b, m, &s);
printf("%.*s\n", t, s); // tsitest
return 0;
}

View file

@ -0,0 +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
(= x y) (cons x (lcs xs ys))
:else (longest (lcs (cons x xs) ys)
(lcs xs (cons y ys)))))))

View file

@ -0,0 +1,30 @@
lcs = (s1, s2) ->
len1 = s1.length
len2 = s2.length
# Create a virtual matrix that is (len1 + 1) by (len2 + 1),
# where m[i][j] is the longest common string using only
# the first i chars of s1 and first j chars of s2. The
# matrix is virtual, because we only keep the last two rows
# in memory.
prior_row = ('' for i in [0..len2])
for i in [0...len1]
row = ['']
for j in [0...len2]
if s1[i] == s2[j]
row.push prior_row[j] + s1[i]
else
subs1 = row[j]
subs2 = prior_row[j+1]
if subs1.length > subs2.length
row.push subs1
else
row.push subs2
prior_row = row
row[len2]
s1 = "thisisatest"
s2 = "testing123testing"
console.log lcs(s1, s2)

View file

@ -0,0 +1,28 @@
(defun longest-common-subsequence (array1 array2)
(let* ((l1 (length array1))
(l2 (length array2))
(results (make-array (list l1 l2) :initial-element nil)))
(declare (dynamic-extent results))
(labels ((lcs (start1 start2)
;; if either sequence is empty, return (() 0)
(if (or (eql start1 l1) (eql start2 l2)) (list '() 0)
;; otherwise, return any memoized value
(let ((result (aref results start1 start2)))
(if (not (null result)) result
;; otherwise, compute and store a value
(setf (aref results start1 start2)
(if (eql (aref array1 start1) (aref array2 start2))
;; if they start with the same element,
;; move forward in both sequences
(destructuring-bind (seq len)
(lcs (1+ start1) (1+ start2))
(list (cons (aref array1 start1) seq) (1+ len)))
;; otherwise, move ahead in each separately,
;; and return the better result.
(let ((a (lcs (1+ start1) start2))
(b (lcs start1 (1+ start2))))
(if (> (second a) (second b))
a
b)))))))))
(destructuring-bind (seq len) (lcs 0 0)
(values (coerce seq (type-of array1)) len)))))

View file

@ -0,0 +1 @@
(longest-common-subsequence "123456" "1a2b3c")

View file

@ -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)))))))

View file

@ -0,0 +1,3 @@
(coerce (lcs (coerce "thisisatest" 'list) (coerce "testing123testing" 'list)) 'string))))
"tsitest"

View file

@ -0,0 +1,13 @@
import std.stdio, std.array;
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 .. $]);
const longest = (T[] x, T[] y) => x.length > y.length ? x : y;
return longest(lcs(a, b[1 .. $]), lcs(a[1 .. $], b));
}
void main() {
lcs("thisisatest", "testing123testing").writeln;
}

View file

@ -0,0 +1,30 @@
import std.stdio, std.algorithm, std.traits;
T[] lcs(T)(in T[] a, in T[] b) pure /*nothrow*/ {
auto L = new uint[][](a.length + 1, b.length + 1);
foreach (immutable i; 0 .. a.length)
foreach (immutable j; 0 .. b.length)
L[i + 1][j + 1] = (a[i] == b[j]) ? (1 + L[i][j]) :
max(L[i + 1][j], L[i][j + 1]);
Unqual!T[] result;
for (auto i = a.length, j = b.length; i > 0 && j > 0; ) {
if (a[i - 1] == b[j - 1]) {
result ~= a[i - 1];
i--;
j--;
} else
if (L[i][j - 1] < L[i - 1][j])
i--;
else
j--;
}
result.reverse(); // Not nothrow.
return result;
}
void main() {
lcs("thisisatest", "testing123testing").writeln;
}

View file

@ -0,0 +1,61 @@
import std.stdio, std.algorithm, std.range, std.array, std.string, std.typecons;
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);
foreach (immutable x; xs) {
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]);
i++;
}
}
return curr;
}
void calculateLCS(T)(in T[] xs, in T[] ys, bool[] xs_in_lcs,
in size_t idx=0) pure nothrow @safe {
immutable nx = xs.length;
immutable ny = ys.length;
if (nx == 0)
return;
if (nx == 1) {
if (ys.canFind(xs[0]))
xs_in_lcs[idx] = true;
} else {
immutable mid = nx / 2;
const xb = xs[0.. mid];
const xe = xs[mid .. $];
immutable ll_b = lensLCS(xb, ys);
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];
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*/ @safe {
auto xs_in_lcs = new bool[xs.length];
calculateLCS(xs, ys, xs_in_lcs);
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*/ @safe {
return lcs(s1.representation, s2.representation).assumeUTF;
}
void main() {
lcsString("thisisatest", "testing123testing").writeln;
}

View file

@ -0,0 +1,67 @@
import 'dart:math';
String lcsRecursion(String a, String b) {
int aLen = a.length;
int bLen = b.length;
if (aLen == 0 || bLen == 0) {
return "";
} else if (a[aLen-1] == b[bLen-1]) {
return lcsRecursion(a.substring(0,aLen-1),b.substring(0,bLen-1)) + a[aLen-1];
} else {
var x = lcsRecursion(a, b.substring(0,bLen-1));
var y = lcsRecursion(a.substring(0,aLen-1), b);
return (x.length > y.length) ? x : y;
}
}
String lcsDynamic(String a, String b) {
var lengths = new List<List<int>>.generate(a.length + 1,
(_) => new List.filled(b.length+1, 0), growable: false);
// row 0 and column 0 are initialized to 0 already
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
lengths[i+1][j+1] = lengths[i][j] + 1;
} else {
lengths[i+1][j+1] = max(lengths[i+1][j], lengths[i][j+1]);
}
}
}
// read the substring out from the matrix
StringBuffer reversedLcsBuffer = new StringBuffer();
for (int x = a.length, y = b.length; x != 0 && y != 0;) {
if (lengths[x][y] == lengths[x-1][y]) {
x--;
} else if (lengths[x][y] == lengths[x][y-1]) {
y--;
} else {
assert(a[x-1] == b[y-1]);
reversedLcsBuffer.write(a[x-1]);
x--;
y--;
}
}
// reverse String
var reversedLCS = reversedLcsBuffer.toString();
var lcsBuffer = new StringBuffer();
for(var i = reversedLCS.length - 1; i>=0; i--) {
lcsBuffer.write(reversedLCS[i]);
}
return lcsBuffer.toString();
}
void main() {
print("lcsDynamic('1234', '1224533324') = ${lcsDynamic('1234', '1224533324')}");
print("lcsDynamic('thisisatest', 'testing123testing') = ${lcsDynamic('thisisatest', 'testing123testing')}");
print("lcsDynamic('', 'x') = ${lcsDynamic('', 'x')}");
print("lcsDynamic('x', 'x') = ${lcsDynamic('x', 'x')}");
print('');
print("lcsRecursion('1234', '1224533324') = ${lcsRecursion('1234', '1224533324')}");
print("lcsRecursion('thisisatest', 'testing123testing') = ${lcsRecursion('thisisatest', 'testing123testing')}");
print("lcsRecursion('', 'x') = ${lcsRecursion('', 'x')}");
print("lcsRecursion('x', 'x') = ${lcsRecursion('x', 'x')}");
}

View file

@ -0,0 +1,8 @@
(define $common-seqs
(lambda [$xs $ys]
(match-all [xs ys] [(list char) (list char)]
[[(loop $i [1 $n] <join _ <cons $c_i ...>> _)
(loop $i [1 ,n] <join _ <cons ,c_i ...>> _)]
(map (lambda [$i] c_i) (between 1 n))])))
(define $lcs (compose common-seqs rac))

View file

@ -0,0 +1,2 @@
> (lcs "thisisatest" "testing123testing"))
"tsitest"

View file

@ -0,0 +1,14 @@
defmodule LCS do
def lcs(a, b) do
lcs(to_charlist(a), to_charlist(b), []) |> to_string
end
defp lcs([h|at], [h|bt], res), do: lcs(at, bt, [h|res])
defp lcs([_|at]=a, [_|bt]=b, res) do
Enum.max_by([lcs(a, bt, res), lcs(at, b, res)], &length/1)
end
defp lcs(_, _, res), do: res |> Enum.reverse
end
IO.puts LCS.lcs("thisisatest", "testing123testing")
IO.puts LCS.lcs('1234','1224533324')

View file

@ -0,0 +1,40 @@
defmodule LCS do
def lcs_length(s,t), do: lcs_length(s,t,Map.new) |> elem(0)
defp lcs_length([],t,cache), do: {0,Map.put(cache,{[],t},0)}
defp lcs_length(s,[],cache), do: {0,Map.put(cache,{s,[]},0)}
defp lcs_length([h|st]=s,[h|tt]=t,cache) do
{l,c} = lcs_length(st,tt,cache)
{l+1,Map.put(c,{s,t},l+1)}
end
defp lcs_length([_sh|st]=s,[_th|tt]=t,cache) do
if Map.has_key?(cache,{s,t}) do
{Map.get(cache,{s,t}),cache}
else
{l1,c1} = lcs_length(s,tt,cache)
{l2,c2} = lcs_length(st,t,c1)
l = max(l1,l2)
{l,Map.put(c2,{s,t},l)}
end
end
def lcs(s,t) do
{s,t} = {to_charlist(s),to_charlist(t)}
{_,c} = lcs_length(s,t,Map.new)
lcs(s,t,c,[]) |> to_string
end
defp lcs([],_,_,acc), do: Enum.reverse(acc)
defp lcs(_,[],_,acc), do: Enum.reverse(acc)
defp lcs([h|st],[h|tt],cache,acc), do: lcs(st,tt,cache,[h|acc])
defp lcs([_sh|st]=s,[_th|tt]=t,cache,acc) do
if Map.get(cache,{s,tt}) > Map.get(cache,{st,t}) do
lcs(s,tt,cache,acc)
else
lcs(st,t,cache,acc)
end
end
end
IO.puts LCS.lcs("thisisatest","testing123testing")
IO.puts LCS.lcs("1234","1224533324")

View file

@ -0,0 +1,41 @@
module(lcs).
-compile(export_all).
lcs_length(S,T) ->
{L,_C} = lcs_length(S,T,dict:new()),
L.
lcs_length([]=S,T,Cache) ->
{0,dict:store({S,T},0,Cache)};
lcs_length(S,[]=T,Cache) ->
{0,dict:store({S,T},0,Cache)};
lcs_length([H|ST]=S,[H|TT]=T,Cache) ->
{L,C} = lcs_length(ST,TT,Cache),
{L+1,dict:store({S,T},L+1,C)};
lcs_length([_SH|ST]=S,[_TH|TT]=T,Cache) ->
case dict:is_key({S,T},Cache) of
true -> {dict:fetch({S,T},Cache),Cache};
false ->
{L1,C1} = lcs_length(S,TT,Cache),
{L2,C2} = lcs_length(ST,T,C1),
L = lists:max([L1,L2]),
{L,dict:store({S,T},L,C2)}
end.
lcs(S,T) ->
{_,C} = lcs_length(S,T,dict:new()),
lcs(S,T,C,[]).
lcs([],_,_,Acc) ->
lists:reverse(Acc);
lcs(_,[],_,Acc) ->
lists:reverse(Acc);
lcs([H|ST],[H|TT],Cache,Acc) ->
lcs(ST,TT,Cache,[H|Acc]);
lcs([_SH|ST]=S,[_TH|TT]=T,Cache,Acc) ->
case dict:fetch({S,TT},Cache) > dict:fetch({ST,T},Cache) of
true ->
lcs(S,TT,Cache, Acc);
false ->
lcs(ST,T,Cache,Acc)
end.

View file

@ -0,0 +1,4 @@
77> lcs:lcs("thisisatest","testing123testing").
"tsitest"
78> lcs:lcs("1234","1224533324").
"1234"

View file

@ -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.

View file

@ -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}.

View file

@ -0,0 +1,2 @@
48> lcs:lcs("thisisatest", "testing123testing").
"tsitest"

View file

@ -0,0 +1,20 @@
open System
let longest xs ys = if List.length xs > List.length ys then xs else ys
let rec lcs a b =
match a, b with
| [], _
| _, [] -> []
| x::xs, y::ys ->
if x = y then
x :: lcs xs ys
else
longest (lcs a ys) (lcs xs b)
[<EntryPoint>]
let main argv =
let split (str:string) = List.init str.Length (fun i -> str.[i])
printfn "%A" (String.Join("",
(lcs (split "thisisatest") (split "testing123testing"))))
0

View file

@ -0,0 +1,2 @@
USE: lcs
"thisisatest" "testing123testing" lcs print

View file

@ -0,0 +1,38 @@
program lcstest
use iso_varying_string
implicit none
type(varying_string) :: s1, s2
s1 = "thisisatest"
s2 = "testing123testing"
print *, char(lcs(s1, s2))
s1 = "1234"
s2 = "1224533324"
print *, char(lcs(s1, s2))
contains
recursive function lcs(a, b) result(l)
type(varying_string) :: l
type(varying_string), intent(in) :: a, b
type(varying_string) :: x, y
l = ""
if ( (len(a) == 0) .or. (len(b) == 0) ) return
if ( extract(a, len(a), len(a)) == extract(b, len(b), len(b)) ) then
l = lcs(extract(a, 1, len(a)-1), extract(b, 1, len(b)-1)) // extract(a, len(a), len(a))
else
x = lcs(a, extract(b, 1, len(b)-1))
y = lcs(extract(a, 1, len(a)-1), b)
if ( len(x) > len(y) ) then
l = x
else
l = y
end if
end if
end function lcs
end program lcstest

View file

@ -0,0 +1,16 @@
Function LCS(a As String, b As String) As String
Dim As String x, y
If Len(a) = 0 Or Len(b) = 0 Then
Return ""
Elseif Right(a, 1) = Right(b, 1) Then
LCS = LCS(Left(a, Len(a) - 1), Left(b, Len(b) - 1)) + Right(a, 1)
Else
x = LCS(a, Left(b, Len(b) - 1))
y = LCS(Left(a, Len(a) - 1), b)
If Len(x) > Len(y) Then Return x Else Return y
End If
End Function
Print LCS("1234", "1224533324")
Print LCS("thisisatest", "testing123testing")
Sleep

View file

@ -0,0 +1,15 @@
func lcs(a, b string) string {
aLen := len(a)
bLen := len(b)
if aLen == 0 || bLen == 0 {
return ""
} else if a[aLen-1] == b[bLen-1] {
return lcs(a[:aLen-1], b[:bLen-1]) + string(a[aLen-1])
}
x := lcs(a, b[:bLen-1])
y := lcs(a[:aLen-1], b)
if len(x) > len(y) {
return x
}
return y
}

View file

@ -0,0 +1,42 @@
func lcs(a, b string) string {
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 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([]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)
}

View file

@ -0,0 +1,23 @@
def lcs(xstr, ystr) {
if (xstr == "" || ystr == "") {
return "";
}
def x = xstr[0];
def y = ystr[0];
def xs = xstr.size() > 1 ? xstr[1..-1] : "";
def ys = ystr.size() > 1 ? ystr[1..-1] : "";
if (x == y) {
return (x + lcs(xs, ys));
}
def lcs1 = lcs(xstr, ys);
def lcs2 = lcs(xs, ystr);
lcs1.size() > lcs2.size() ? lcs1 : lcs2;
}
println(lcs("1234", "1224533324"));
println(lcs("thisisatest", "testing123testing"));

View file

@ -0,0 +1,7 @@
longest xs ys = if length xs > length ys then xs else ys
lcs [] _ = []
lcs _ [] = []
lcs (x:xs) (y:ys)
| x == y = x : lcs xs ys
| otherwise = longest (lcs (x:xs) ys) (lcs xs (y:ys))

View file

@ -0,0 +1,13 @@
import qualified Data.MemoCombinators as M
lcs = memoize lcsm
where
lcsm [] _ = []
lcsm _ [] = []
lcsm (x:xs) (y:ys)
| x == y = x : lcs xs ys
| otherwise = maxl (lcs (x:xs) ys) (lcs xs (y:ys))
maxl x y = if length x > length y then x else y
memoize = M.memo2 mString mString
mString = M.list M.char -- Chars, but you can specify any type you need for the memo

View file

@ -0,0 +1,12 @@
import Data.Array
lcs xs ys = a!(0,0) where
n = length xs
m = length ys
a = array ((0,0),(n,m)) $ l1 ++ l2 ++ l3
l1 = [((i,m),[]) | i <- [0..n]]
l2 = [((n,j),[]) | j <- [0..m]]
l3 = [((i,j), f x y i j) | (x,i) <- zip xs [0..], (y,j) <- zip ys [0..]]
f x y i j
| x == y = x : a!(i+1,j+1)
| otherwise = longest (a!(i,j+1)) (a!(i+1,j))

View file

@ -0,0 +1,2 @@
*Main> lcs "thisisatest" "testing123testing"
"tsitest"

View file

@ -0,0 +1,10 @@
import Data.List
longest xs ys = if length xs > length ys then xs else ys
lcs xs ys = head $ foldr(\xs -> map head. scanr1 f. zipWith (\x y -> [x,y]) xs) e m where
m = map (\x -> flip (++) [[]] $ map (\y -> [x | x==y]) ys) xs
e = replicate (length ys) []
f [a,b] [c,d]
| null a = longest b c: [b]
| otherwise = (a++d):[b]

View file

@ -0,0 +1,7 @@
import Data.Ord
import Data.List
-- longest common
lcs xs ys = maximumBy (comparing length) $ intersect (subsequences xs) (subsequences ys)
main = print $ lcs "thisisatest" "testing123testing"

View file

@ -0,0 +1,36 @@
procedure main()
LCSTEST("thisisatest","testing123testing")
LCSTEST("","x")
LCSTEST("x","x")
LCSTEST("beginning-middle-ending","beginning-diddle-dum-ending")
end
link strings
procedure LCSTEST(a,b) #: helper to show inputs and results
write("lcs( ",image(a),", ",image(b)," ) = ",image(res := lcs(a,b)))
return res
end
procedure lcs(a,b) #: return longest common sub-sequence of characters (modified recursive method)
local i,x,y
local c,nc
if *(a|b) = 0 then return "" # done if either string is empty
if a == b then return a # done if equal
if *(a ++ b -- (c := a ** b)) > 0 then { # find all characters not in common
a := deletec(a,nc := ~c) # .. remove
b := deletec(b,nc) # .. remove
} # only unequal strings and shared characters beyond
i := 0 ; while a[i+1] == b[i+1] do i +:=1 # find common prefix ...
if *(x := a[1+:i]) > 0 then # if any
return x || lcs(a[i+1:0],b[i+1:0]) # ... remove and process remainder
i := 0 ; while a[-(i+1)] == b[-(i+1)] do i +:=1 # find common suffix ...
if *(y := a[0-:i]) > 0 then # if any
return lcs(a[1:-i],b[1:-i]) || y # ... remove and process remainder
return if *(x := lcs(a,b[1:-1])) > *(y := lcs(a[1:-1],b)) then x else y # divide, discard, and keep longest
end

View file

@ -0,0 +1,5 @@
lcs=: dyad define
|.x{~ 0{"1 cullOne^:_ (\: +/"1)(\:{."1) 4$.$. x =/ y
)
cullOne=: ({~[: <@<@< [: (i. 0:)1,[: *./[: |: 2>/\]) :: ]

View file

@ -0,0 +1,3 @@
mergeSq=: ;@}: ~.@, {.@;@{. ,&.> 3 {:: 4&{.
common=: 2 2 <@mergeSq@,;.3^:_ [: (<@#&.> i.@$) =/
lcs=: [ {~ 0 {"1 ,&$ #: 0 ({:: (#~ [: (= >./) #@>)) 0 ({:: ,) common

View file

@ -0,0 +1,2 @@
'thisisatest' lcs 'testing123testing'
tsitest

View file

@ -0,0 +1,3 @@
longest=: ]`[@.(>&#)
upd=:{:@[,~ ({.@[ ,&.> {:@])`({:@[ longest&.> {.@])@.(0 = #&>@{.@[)
lcs=: 0{:: [: ([: {.&> [: upd&.>/\.<"1@:,.)/ a:,.~a:,~=/{"1 a:,.<"0@[

View file

@ -0,0 +1,5 @@
'1234' lcs '1224533324'
1234
'thisisatest' lcs 'testing123testing'
tsitest

View file

@ -0,0 +1 @@
lcs=:;(($:}.) longest }.@[ $: ])`({.@[,$:&}.)@.(=&{.)`((i.0)"_)@.(+.&(0=#))&((e.#[)&>/) ;~

View file

@ -0,0 +1,14 @@
public static String lcs(String a, String b){
int aLen = a.length();
int bLen = b.length();
if(aLen == 0 || bLen == 0){
return "";
}else if(a.charAt(aLen-1) == b.charAt(bLen-1)){
return lcs(a.substring(0,aLen-1),b.substring(0,bLen-1))
+ a.charAt(aLen-1);
}else{
String x = lcs(a, b.substring(0,bLen-1));
String y = lcs(a.substring(0,aLen-1), b);
return (x.length() > y.length()) ? x : y;
}
}

View file

@ -0,0 +1,31 @@
public static String lcs(String a, String b) {
int[][] lengths = new int[a.length()+1][b.length()+1];
// row 0 and column 0 are initialized to 0 already
for (int i = 0; i < a.length(); i++)
for (int j = 0; j < b.length(); j++)
if (a.charAt(i) == b.charAt(j))
lengths[i+1][j+1] = lengths[i][j] + 1;
else
lengths[i+1][j+1] =
Math.max(lengths[i+1][j], lengths[i][j+1]);
// read the substring out from the matrix
StringBuffer sb = new StringBuffer();
for (int x = a.length(), y = b.length();
x != 0 && y != 0; ) {
if (lengths[x][y] == lengths[x-1][y])
x--;
else if (lengths[x][y] == lengths[x][y-1])
y--;
else {
assert a.charAt(x-1) == b.charAt(y-1);
sb.append(a.charAt(x-1));
x--;
y--;
}
}
return sb.reverse().toString();
}

View file

@ -0,0 +1,14 @@
function lcs(a, b) {
var aSub = a.substr(0, a.length - 1);
var bSub = b.substr(0, b.length - 1);
if (a.length === 0 || b.length === 0) {
return '';
} else if (a.charAt(a.length - 1) === b.charAt(b.length - 1)) {
return lcs(aSub, bSub) + a.charAt(a.length - 1);
} else {
var x = lcs(a, bSub);
var y = lcs(aSub, b);
return (x.length > y.length) ? x : y;
}
}

View file

@ -0,0 +1,10 @@
const longest = (xs, ys) => (xs.length > ys.length) ? xs : ys;
const lcs = (xx, yy) => {
if (!xx.length || !yy.length) { return ''; }
const [x, ...xs] = xx;
const [y, ...ys] = yy;
return (x === y) ? (x + lcs(xs, ys)) : longest(lcs(xx, ys), lcs(xs, yy));
};

View file

@ -0,0 +1,35 @@
function lcs(x,y){
var s,i,j,m,n,
lcs=[],row=[],c=[],
left,diag,latch;
//make sure shorter string is the column string
if(m<n){s=x;x=y;y=s;}
m = x.length;
n = y.length;
//build the c-table
for(j=0;j<n;row[j++]=0);
for(i=0;i<m;i++){
c[i] = row = row.slice();
for(diag=0,j=0;j<n;j++,diag=latch){
latch=row[j];
if(x[i] == y[j]){row[j] = diag+1;}
else{
left = row[j-1]||0;
if(left>row[j]){row[j] = left;}
}
}
}
i--,j--;
//row[j] now contains the length of the lcs
//recover the lcs from the table
while(i>-1&&j>-1){
switch(c[i][j]){
default: j--;
lcs.unshift(x[i]);
case (i&&c[i-1][j]): i--;
continue;
case (j&&c[i][j-1]): j--;
}
}
return lcs.join('');
}

View file

@ -0,0 +1,15 @@
var t=i;
while(i>-1&&j>-1){
switch(c[i][j]){
default:i--,j--;
continue;
case (i&&c[i-1][j]):
if(t!==i){lcs.unshift(x.substring(i+1,t+1));}
t=--i;
continue;
case (j&&c[i][j-1]): j--;
if(t!==i){lcs.unshift(x.substring(i+1,t+1));}
t=i;
}
}
if(t!==i){lcs.unshift(x.substring(i+1,t+1));}

View file

@ -0,0 +1,42 @@
function lcs_greedy(x,y){
var p1, i, idx,
symbols = {},
r = 0,
p = 0,
l = 0,
m = x.length,
n = y.length,
s = new Buffer((m < n) ? n : m);
p1 = popsym(0);
for (i = 0; i < m; i++) {
p = (r === p) ? p1 : popsym(i);
p1 = popsym(i + 1);
if (p > p1) {
i += 1;
idx = p1;
} else {
idx = p;
}
if (idx === n) {
p = popsym(i);
} else {
r = idx;
s[l] = x.charCodeAt(i);
l += 1;
}
}
return s.toString('utf8', 0, l);
function popsym(index) {
var s = x[index],
pos = symbols[s] + 1;
pos = y.indexOf(s, ((pos > r) ? pos : r));
if (pos === -1) { pos = n; }
symbols[s] = pos;
return pos;
}
}

View file

@ -0,0 +1 @@
lcs_greedy('bcaaaade', 'deaaaabc'); // 'bc' instead of 'aaaa'

View file

@ -0,0 +1,13 @@
def lcs(xstr; ystr):
if (xstr == "" or ystr == "") then ""
else
xstr[0:1] as $x
| xstr[1:] as $xs
| ystr[1:] as $ys
| if ($x == ystr[0:1]) then ($x + lcs($xs; $ys))
else
lcs(xstr; $ys) as $one
| lcs($xs; ystr) as $two
| if ($one|length) > ($two|length) then $one else $two end
end
end;

View file

@ -0,0 +1,2 @@
lcs("1234"; "1224533324"),
lcs("thisisatest"; "testing123testing")

View file

@ -0,0 +1,3 @@
# jq -n -f lcs-recursive.jq
"1234"
"tsitest"

View file

@ -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")

View file

@ -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))
}

View file

@ -0,0 +1,31 @@
'variation of BASIC example
w$="aebdef"
z$="cacbc"
print lcs$(w$,z$)
'output:
'ab
wait
FUNCTION lcs$(a$, b$)
IF LEN(a$) = 0 OR LEN(b$) = 0 THEN
lcs$ = ""
exit function
end if
IF RIGHT$(a$, 1) = RIGHT$(b$, 1) THEN
lcs$ = lcs$(LEFT$(a$, LEN(a$) - 1), LEFT$(b$, LEN(b$) - 1)) + RIGHT$(a$, 1)
exit function
ELSE
x$ = lcs$(a$, LEFT$(b$, LEN(b$) - 1))
y$ = lcs$(LEFT$(a$, LEN(a$) - 1), b$)
IF LEN(x$) > LEN(y$) THEN
lcs$ = x$
exit function
ELSE
lcs$ = y$
exit function
END IF
END IF
END FUNCTION

View file

@ -0,0 +1,9 @@
to longest :s :t
output ifelse greater? count :s count :t [:s] [:t]
end
to lcs :s :t
if empty? :s [output :s]
if empty? :t [output :t]
if equal? first :s first :t [output combine first :s lcs bf :s bf :t]
output longest lcs :s bf :t lcs bf :s :t
end

View file

@ -0,0 +1,18 @@
function LCS( a, b )
if #a == 0 or #b == 0 then
return ""
elseif string.sub( a, -1, -1 ) == string.sub( b, -1, -1 ) then
return LCS( string.sub( a, 1, -2 ), string.sub( b, 1, -2 ) ) .. string.sub( a, -1, -1 )
else
local a_sub = LCS( a, string.sub( b, 1, -2 ) )
local b_sub = LCS( string.sub( a, 1, -2 ), b )
if #a_sub > #b_sub then
return a_sub
else
return b_sub
end
end
end
print( LCS( "thisisatest", "testing123testing" ) )

View file

@ -0,0 +1,21 @@
define(`set2d',`define(`$1[$2][$3]',`$4')')
define(`get2d',`defn($1[$2][$3])')
define(`tryboth',
`pushdef(`x',lcs(`$1',substr(`$2',1),`$1 $2'))`'pushdef(`y',
lcs(substr(`$1',1),`$2',`$1 $2'))`'ifelse(eval(len(x)>len(y)),1,
`x',`y')`'popdef(`x')`'popdef(`y')')
define(`checkfirst',
`ifelse(substr(`$1',0,1),substr(`$2',0,1),
`substr(`$1',0,1)`'lcs(substr(`$1',1),substr(`$2',1))',
`tryboth(`$1',`$2')')')
define(`lcs',
`ifelse(get2d(`c',`$1',`$2'),`',
`pushdef(`a',ifelse(
`$1',`',`',
`$2',`',`',
`checkfirst(`$1',`$2')'))`'a`'set2d(`c',`$1',`$2',a)`'popdef(`a')',
`get2d(`c',`$1',`$2')')')
lcs(`1234',`1224533324')
lcs(`thisisatest',`testing123testing')

View file

@ -0,0 +1,2 @@
> StringTools:-LongestCommonSubSequence( "thisisatest", "testing123testing" );
"tsitest"

View file

@ -0,0 +1,3 @@
a = "thisisatest";
b = "testing123testing";
LongestCommonSequence[a, b]

View file

@ -0,0 +1,13 @@
proc lcs(x, y: string): string =
if x == "" or y == "":
return ""
if x[0] == y[0]:
return x[0] & lcs(x[1..x.high], y[1..y.high])
let a = lcs(x, y[1..y.high])
let b = lcs(x[1..x.high], y)
result = if a.len > b.len: a else: b
echo lcs("1234", "1224533324")
echo lcs("thisisatest", "testing123testing")

View file

@ -0,0 +1,28 @@
proc lcs(a, b: string): string =
var ls = newSeq[seq[int]](a.len+1)
for i in 0 .. a.len:
ls[i].newSeq(b.len+1)
for i, x in a:
for j, y in b:
if x == y:
ls[i+1][j+1] = ls[i][j] + 1
else:
ls[i+1][j+1] = max(ls[i+1][j], ls[i][j+1])
result = ""
var x = a.len
var y = b.len
while x > 0 and y > 0:
if ls[x][y] == ls[x-1][y]:
dec x
elif ls[x][y] == ls[x][y-1]:
dec y
else:
assert a[x-1] == b[y-1]
result = a[x-1] & result
dec x
dec y
echo lcs("1234", "1224533324")
echo lcs("thisisatest", "testing123testing")

View file

@ -0,0 +1,10 @@
let longest xs ys = if List.length xs > List.length ys then xs else ys
let rec lcs a b = match a, b with
[], _
| _, [] -> []
| x::xs, y::ys ->
if x = y then
x :: lcs xs ys
else
longest (lcs a ys) (lcs xs b)

View file

@ -0,0 +1,20 @@
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

View file

@ -0,0 +1,15 @@
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)

View file

@ -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

View file

@ -0,0 +1,15 @@
declare
fun {LCS Xs Ys}
case [Xs Ys]
of [nil _] then nil
[] [_ nil] then nil
[] [X|Xr Y|Yr] andthen X==Y then X|{LCS Xr Yr}
[] [_|Xr _|Yr] then {Longest {LCS Xs Yr} {LCS Xr Ys}}
end
end
fun {Longest Xs Ys}
if {Length Xs} > {Length Ys} then Xs else Ys end
end
in
{System.showInfo {LCS "thisisatest" "testing123testing"}}

View file

@ -0,0 +1,34 @@
Program LongestCommonSubsequence(output);
function lcs(a, b: string): string;
var
x, y: string;
lenga, lengb: integer;
begin
lenga := length(a);
lengb := length(b);
lcs := '';
if (lenga > 0) and (lengb > 0) then
if a[lenga] = b[lengb] then
lcs := lcs(copy(a, 1, lenga-1), copy(b, 1, lengb-1)) + a[lenga]
else
begin
x := lcs(a, copy(b, 1, lengb-1));
y := lcs(copy(a, 1, lenga-1), b);
if length(x) > length(y) then
lcs := x
else
lcs := y;
end;
end;
var
s1, s2: string;
begin
s1 := 'thisisatest';
s2 := 'testing123testing';
writeln (lcs(s1, s2));
s1 := '1234';
s2 := '1224533324';
writeln (lcs(s1, s2));
end.

View file

@ -0,0 +1,14 @@
sub lcs {
my ($a, $b) = @_;
if (!length($a) || !length($b)) {
return "";
}
if (substr($a, 0, 1) eq substr($b, 0, 1)) {
return substr($a, 0, 1) . lcs(substr($a, 1), substr($b, 1));
}
my $c = lcs(substr($a, 1), $b) || "";
my $d = lcs($a, substr($b, 1)) || "";
return length($c) > length($d) ? $c : $d;
}
print lcs("thisisatest", "testing123testing") . "\n";

View file

@ -0,0 +1,16 @@
use strict;
use warnings;
use feature 'bitwise';
print "lcs is ", lcs('thisisatest', 'testing123testing'), "\n";
sub lcs
{
my ($c, $d) = @_;
for my $len ( reverse 1 .. length($c &. $d) )
{
"$c\n$d" =~ join '.*', ('(.)') x $len, "\n", map "\\$_", 1 .. $len and
return join '', @{^CAPTURE};
}
return '';
}

View file

@ -0,0 +1,23 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[$]=</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[$]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])&</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[$]</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]),</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">l</span><span style="color: #0000FF;">:</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"1234"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1224533324"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"thisisatest"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"testing123testing"</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--

View file

@ -0,0 +1,41 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">LCSLength</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">Y</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">C</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Y</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">X</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">X</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Y</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">Y</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">C</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">backtrack</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">Y</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">Y</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">backtrack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]></span><span style="color: #000000;">C</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">backtrack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">backtrack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">X</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">backtrack</span><span style="color: #0000FF;">(</span><span style="color: #000000;">LCSLength</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"1234"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1224533324"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"thisisatest"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"testing123testing"</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">lcs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--

View file

@ -0,0 +1,29 @@
lcs_wiki(X,Y) = V =>
[C, _Len] = lcs_length(X,Y),
V = backTrace(C,X,Y,X.length+1,Y.length+1).
lcs_length(X, Y) = V=>
M = X.length,
N = Y.length,
C = [[0 : J in 1..N+1] : I in 1..N+1],
foreach(I in 2..M+1,J in 2..N+1)
if X[I-1] == Y[J-1] then
C[I,J] := C[I-1,J-1] + 1
else
C[I,J] := max([C[I,J-1], C[I-1,J]])
end
end,
V = [C, C[M+1,N+1]].
backTrace(C, X, Y, I, J) = V =>
if I == 1; J == 1 then
V = ""
elseif X[I-1] == Y[J-1] then
V = backTrace(C, X, Y, I-1, J-1) ++ [X[I-1]]
else
if C[I,J-1] > C[I-1,J] then
V = backTrace(C, X, Y, I, J-1)
else
V = backTrace(C, X, Y, I-1, J)
end
end.

View file

@ -0,0 +1,10 @@
table
lcs_rule(A, B) = "", (A == ""; B == "") => true.
lcs_rule(A, B) = [A[1]] ++ lcs_rule(butfirst(A), butfirst(B)), A[1] == B[1] => true.
lcs_rule(A, B) = longest(lcs_rule(butfirst(A), B), lcs_rule(A, butfirst(B))) => true.
% Return the longest string of A and B
longest(A, B) = cond(A.length > B.length, A, B).
% butfirst (everything except first element)
butfirst(A) = [A[I] : I in 2..A.length].

View file

@ -0,0 +1,17 @@
go =>
Tests = [["thisisatest","testing123testing"],
["XMJYAUZ", "MZJAWXU"],
["1234", "1224533324"],
["beginning-middle-ending","beginning-diddle-dum-ending"]
],
Funs = [lcs_wiki,lcs_rule],
foreach(Fun in Funs)
println(fun=Fun),
foreach(Test in Tests)
printf("%w : %w\n", Test, apply(Fun,Test[1],Test[2]))
end,
nl
end,
nl.

View file

@ -0,0 +1,12 @@
(de commonSequences (A B)
(when A
(conc
(when (member (car A) B)
(mapcar '((L) (cons (car A) L))
(cons NIL (commonSequences (cdr A) (cdr @))) ) )
(commonSequences (cdr A) B) ) ) )
(maxi length
(commonSequences
(chop "thisisatest")
(chop "testing123testing") ) )

View file

@ -0,0 +1,47 @@
function Get-Lcs ($ReferenceObject, $DifferenceObject)
{
$longestCommonSubsequence = @()
$x = $ReferenceObject.Length
$y = $DifferenceObject.Length
$lengths = New-Object -TypeName 'System.Object[,]' -ArgumentList ($x + 1), ($y + 1)
for($i = 0; $i -lt $x; $i++)
{
for ($j = 0; $j -lt $y; $j++)
{
if ($ReferenceObject[$i] -ceq $DifferenceObject[$j])
{
$lengths[($i+1),($j+1)] = $lengths[$i,$j] + 1
}
else
{
$lengths[($i+1),($j+1)] = [Math]::Max(($lengths[($i+1),$j]),($lengths[$i,($j+1)]))
}
}
}
while (($x -ne 0) -and ($y -ne 0))
{
if ( $lengths[$x,$y] -eq $lengths[($x-1),$y])
{
--$x
}
elseif ($lengths[$x,$y] -eq $lengths[$x,($y-1)])
{
--$y
}
else
{
if ($ReferenceObject[($x-1)] -ceq $DifferenceObject[($y-1)])
{
$longestCommonSubsequence = ,($ReferenceObject[($x-1)]) + $longestCommonSubsequence
}
--$x
--$y
}
}
$longestCommonSubsequence
}

View file

@ -0,0 +1 @@
(Get-Lcs -ReferenceObject "thisisatest" -DifferenceObject "testing123testing") -join ""

View file

@ -0,0 +1 @@
Get-Lcs -ReferenceObject @(1,2,3,4) -DifferenceObject @(1,2,2,4,5,3,3,3,2,4)

View file

@ -0,0 +1,25 @@
$list1
ID X Y
-- - -
1 101 201
2 102 202
3 103 203
4 104 204
5 105 205
6 106 206
7 107 207
8 108 208
9 109 209
$list2
ID X Y
-- - -
1 101 201
3 103 203
5 105 205
7 107 207
9 109 209
Get-Lcs -ReferenceObject $list1.ID -DifferenceObject $list2.ID

View file

@ -0,0 +1,20 @@
test :-
time(lcs("thisisatest", "testing123testing", Lcs)),
writef('%s',[Lcs]).
lcs([ H|L1],[ H|L2],[H|Lcs]) :- !,
lcs(L1,L2,Lcs).
lcs([H1|L1],[H2|L2],Lcs):-
lcs( L1 ,[H2|L2],Lcs1),
lcs([H1|L1], L2 ,Lcs2),
longest(Lcs1,Lcs2,Lcs),!.
lcs(_,_,[]).
longest(L1,L2,Longest) :-
length(L1,Length1),
length(L2,Length2),
((Length1 > Length2) -> Longest = L1; Longest = L2).

Some files were not shown because too many files have changed in this diff Show more