Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
5
Task/Longest-common-subsequence/00-META.yaml
Normal file
5
Task/Longest-common-subsequence/00-META.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Recursion
|
||||
- Memoization
|
||||
from: http://rosettacode.org/wiki/Longest_common_subsequence
|
||||
94
Task/Longest-common-subsequence/00-TASK.txt
Normal file
94
Task/Longest-common-subsequence/00-TASK.txt
Normal 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.'' 275–281]
|
||||
<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>
|
||||
|
||||
|
|
@ -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’))
|
||||
|
|
@ -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))
|
||||
)
|
||||
|
|
@ -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,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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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$
|
||||
|
|
@ -0,0 +1 @@
|
|||
LCS ← ¯1 ⊑ "" <⊸∾ ""¨∘⊢ ⊣⍟(>○≠){𝕩𝔽¨𝔽`𝕨∾¨""<⊸»𝕩}˝ (=⌜⥊¨⊣)⟜⌽
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
"1234" LCS "1224533324"
|
||||
"1234"
|
||||
"thisisatest" LCS "testing123testing"
|
||||
"tsitest"
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
auto s = LCS::Correspondence(s1, s2);
|
||||
cout << s << endl;
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)))))))
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)))))
|
||||
|
|
@ -0,0 +1 @@
|
|||
(longest-common-subsequence "123456" "1a2b3c")
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
"123"
|
||||
3
|
||||
|
|
@ -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"
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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')}");
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
> (lcs "thisisatest" "testing123testing"))
|
||||
"tsitest"
|
||||
|
|
@ -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')
|
||||
|
|
@ -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")
|
||||
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
77> lcs:lcs("thisisatest","testing123testing").
|
||||
"tsitest"
|
||||
78> lcs:lcs("1234","1224533324").
|
||||
"1234"
|
||||
|
|
@ -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.
|
||||
|
|
@ -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,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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
USE: lcs
|
||||
"thisisatest" "testing123testing" lcs print
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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"));
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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))
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
*Main> lcs "thisisatest" "testing123testing"
|
||||
"tsitest"
|
||||
|
|
@ -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]
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
lcs=: dyad define
|
||||
|.x{~ 0{"1 cullOne^:_ (\: +/"1)(\:{."1) 4$.$. x =/ y
|
||||
)
|
||||
|
||||
cullOne=: ({~[: <@<@< [: (i. 0:)1,[: *./[: |: 2>/\]) :: ]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
mergeSq=: ;@}: ~.@, {.@;@{. ,&.> 3 {:: 4&{.
|
||||
common=: 2 2 <@mergeSq@,;.3^:_ [: (<@#&.> i.@$) =/
|
||||
lcs=: [ {~ 0 {"1 ,&$ #: 0 ({:: (#~ [: (= >./) #@>)) 0 ({:: ,) common
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
'thisisatest' lcs 'testing123testing'
|
||||
tsitest
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
longest=: ]`[@.(>&#)
|
||||
upd=:{:@[,~ ({.@[ ,&.> {:@])`({:@[ longest&.> {.@])@.(0 = #&>@{.@[)
|
||||
lcs=: 0{:: [: ([: {.&> [: upd&.>/\.<"1@:,.)/ a:,.~a:,~=/{"1 a:,.<"0@[
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
'1234' lcs '1224533324'
|
||||
1234
|
||||
|
||||
'thisisatest' lcs 'testing123testing'
|
||||
tsitest
|
||||
|
|
@ -0,0 +1 @@
|
|||
lcs=:;(($:}.) longest }.@[ $: ])`({.@[,$:&}.)@.(=&{.)`((i.0)"_)@.(+.&(0=#))&((e.#[)&>/) ;~
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
};
|
||||
|
|
@ -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('');
|
||||
}
|
||||
|
|
@ -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));}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
lcs_greedy('bcaaaade', 'deaaaabc'); // 'bc' instead of 'aaaa'
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
lcs("1234"; "1224533324"),
|
||||
lcs("thisisatest"; "testing123testing")
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# jq -n -f lcs-recursive.jq
|
||||
"1234"
|
||||
"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,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
|
||||
|
|
@ -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
|
||||
|
|
@ -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" ) )
|
||||
|
|
@ -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')
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
> StringTools:-LongestCommonSubSequence( "thisisatest", "testing123testing" );
|
||||
"tsitest"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
a = "thisisatest";
|
||||
b = "testing123testing";
|
||||
LongestCommonSequence[a, b]
|
||||
|
|
@ -0,0 +1 @@
|
|||
tsitest
|
||||
|
|
@ -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")
|
||||
|
|
@ -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")
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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"}}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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";
|
||||
|
|
@ -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 '';
|
||||
}
|
||||
|
|
@ -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>
|
||||
<!--
|
||||
|
|
@ -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>
|
||||
<!--
|
||||
|
|
@ -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.
|
||||
|
|
@ -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].
|
||||
|
|
@ -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.
|
||||
|
|
@ -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") ) )
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
(Get-Lcs -ReferenceObject "thisisatest" -DifferenceObject "testing123testing") -join ""
|
||||
|
|
@ -0,0 +1 @@
|
|||
Get-Lcs -ReferenceObject @(1,2,3,4) -DifferenceObject @(1,2,2,4,5,3,3,3,2,4)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue