From 2896eb758971260f5ae446b8c8ef5303b3a326f9 Mon Sep 17 00:00:00 2001 From: rulanugrh Date: Tue, 12 Mar 2024 16:18:15 +0700 Subject: [PATCH] feat: adding testing for kmp algorithm --- algorithm/algorithm_test.go | 16 ++++++ algorithm/kmp.go | 105 ++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 algorithm/kmp.go diff --git a/algorithm/algorithm_test.go b/algorithm/algorithm_test.go index e438308..a16f720 100644 --- a/algorithm/algorithm_test.go +++ b/algorithm/algorithm_test.go @@ -12,3 +12,19 @@ func TestCompressLZW(t *testing.T) { assert.Equal(t, expected, str) } + +func TestKMP(t *testing.T) { + str := SearchString("syahara", "sy") + + assert.Equal(t, 0, str) +} + +func TestKMPLast(t *testing.T) { + str := SerchNext("syahara", "ha") + assert.Equal(t, 3, str) +} + +func TestKMPNone(t *testing.T) { + str := SearchString("araa", "rul") + assert.Equal(t, -1, str) +} diff --git a/algorithm/kmp.go b/algorithm/kmp.go new file mode 100644 index 0000000..082e613 --- /dev/null +++ b/algorithm/kmp.go @@ -0,0 +1,105 @@ +package algorithm + + +const ( + PatternSize int = 100 +) + +func SerchNext(stack string, needle string) int { + ret := KMP(stack, needle) + if len(ret) > 0 { + return ret[len(ret)-1] + } + + return -1 +} + +func SearchString(stack string, needle string) int { + + ret := KMP(stack, needle) + if len(ret) > 0 { + return ret[0] + } + + return -1 +} + +func KMP(stack string, needle string) []int { + next := preKMP(needle) + i := 0 + j := 0 + m := len(needle) + n := len(stack) + + x := []byte(needle) + y := []byte(stack) + var ret []int + + if m == 0 || n == 0 { + return ret + } + + if n < m { + return ret + } + + for j < n { + for i > -1 && x[i] != y[j] { + i = next[i] + } + i++ + j++ + + if i >= m { + ret = append(ret, j-i) + i = next[i] + } + } + + return ret +} +func preMP(x string) [PatternSize]int { + var i, j int + lenght := len(x) - 1 + + var mpNext [PatternSize]int + i = 0 + j = -1 + mpNext[0] = -1 + + for i < lenght { + for j > -1 && x[i] != x[j] { + j = mpNext[j] + } + i++ + j++ + mpNext[i] = j + } + + return mpNext +} + +func preKMP(x string) [PatternSize]int { + var i, j int + lenght := len(x) - 1 + + var kmpNext [PatternSize]int + i = 0 + j = -1 + kmpNext[0] = -1 + + for i < lenght { + for j > -1 && x[i] != x[j] { + j = kmpNext[j] + } + i++ + j++ + + if x[i] == x[j] { + kmpNext[i] = kmpNext[j] + } else { + kmpNext[i] = j + } + } + return kmpNext +}