Skip to content

Commit

Permalink
Merge pull request #12 from choilmto/add_lcs
Browse files Browse the repository at this point in the history
Add longest common subsequence algorithm and concomitant tests.
  • Loading branch information
antzucaro committed Feb 22, 2021
2 parents ab6ba46 + 085cf1d commit b04723e
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
30 changes: 30 additions & 0 deletions longestcommonsubsequence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package matchr

// LongestCommonSubsequence computes the longest substring
// between two strings. The returned value is the length
// of the substring, which contains letters from both
// strings, while maintaining the order of the letters.
func LongestCommonSubsequence(s1, s2 string) int {
r1 := []rune(s1)
r2 := []rune(s2)
table := make([][]int, len(s1)+1)

// Construct 2D table
for i := range table {
table[i] = make([]int, len(s2)+1)
}

var i int
var j int

for i = len(r1) - 1; i >= 0; i-- {
for j = len(r2) - 1; j >= 0; j-- {
if r1[i] == r2[j] {
table[i][j] = 1 + table[i+1][j+1]
} else {
table[i][j] = maxI(table[i+1][j], table[i][j+1])
}
}
}
return table[0][0]
}
33 changes: 33 additions & 0 deletions longestcommonsubsequence_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package matchr

import "testing"

var lcstests = []struct {
s1 string
s2 string
length int
}{
// match beginning
{"cans", "can", 3},
// match end
{"ebay", "bay", 3},
// gap in the middle
{"coins", "cons", 4},
// one empty, left
{"", "hello", 0},
// one empty, right
{"goodbye", "", 0},
// two empties
{"", "", 0},
// unicode stuff!
{"Schüßler", "Schüßler", 8},
}

func TestLongestCommonSubsequence(t *testing.T) {
for _, tt := range lcstests {
length := LongestCommonSubsequence(tt.s1, tt.s2)
if length != tt.length {
t.Errorf("LongestCommonSubsequence('%s', '%s') = %v, want %v", tt.s1, tt.s2, length, tt.length)
}
}
}

0 comments on commit b04723e

Please sign in to comment.