changeset 2:b7160d5e22cc

Add longest common/increasing subsequence algorithms
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 12 Feb 2023 21:06:13 +0100
parents ed34696a9d9b
children c1db337c15be
files longest_common_subsequence.jl longest_increasing_subsequence.jl
diffstat 2 files changed, 72 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/longest_common_subsequence.jl	Sun Feb 12 21:06:13 2023 +0100
@@ -0,0 +1,38 @@
+function longest_common_subsequence(x::Vector{T}, y::Vector{T})::Vector{T} where {T}
+    m, n = length(x), length(y)
+    C = zeros(Int, m+1, n+1)
+    # Not necessary:
+    for i = 1:m
+        C[i,1] = 0
+    end
+    for j = 1:n
+        C[1,j] = 0
+    end
+    for i = 1:m
+        for j = 1:n
+            if x[i] == y[j]
+                C[i+1,j+1] = C[i, j] + 1
+            else
+                C[i+1,j+1] = max(C[i, j+1], C[i+1, j])
+            end
+        end
+    end
+
+    # Reconstruct sequence
+    i, j = m, n
+    k = C[m+1, n+1]
+    seq = Vector{T}(undef, k)
+    while k > 0
+        if C[i,j] + 1 == C[i+1,j+1]
+            seq[k] = x[i]
+            k -= 1
+            i -= 1
+            j -= 1
+        elseif C[i,j+1] == C[i+1,j+1]
+            i -= 1
+        elseif C[i+1,j] == C[i+1,j+1]
+            j -= 1
+        end
+    end
+    seq
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/longest_increasing_subsequence.jl	Sun Feb 12 21:06:13 2023 +0100
@@ -0,0 +1,34 @@
+function longest_increasing_subsequence(v::Vector{Int})::Vector{Int}
+    M = zeros(Int, length(v)) # M[L] stores last index of sequence with length L.
+    P = zeros(Int, length(v)) # P[i] stores predecessor of element i in longest sequence.
+    Longest = 0
+    for i = eachindex(v)
+        # Binary search for position in longest-sequence-so-far
+        lo, hi = 1, Longest+1
+        while lo < hi
+            mid = round(Int, floor((lo+hi)/2))
+            if v[i] < v[M[mid]]
+                hi = mid
+            else
+                lo = mid+1
+            end
+        end
+        @assert lo == hi
+        # Update predecessor of current index.
+        P[i] = lo > 1 ? M[lo-1] : -1
+        M[lo] = i
+
+        if lo >= Longest
+            Longest = lo
+        end
+    end
+
+    # Reconstruct sequence.
+    seq = zeros(Int, Longest)
+    i = M[Longest]
+    for j = Longest:-1:1
+        seq[j] = v[i]
+        i = P[i]
+    end
+    seq
+end