Last active
December 28, 2020 04:37
-
-
Save khiav223577/51bf1fb07e0eabe4908e4dc293167e6f to your computer and use it in GitHub Desktop.
KMP algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
def kmp_table(pattern) | |
i = 0 | |
j = 1 | |
table = [0] | |
while j < pattern.size | |
if pattern[i] == pattern[j] | |
i += 1 | |
else | |
i = table[i - 1] and next if i > 0 | |
end | |
table[j] = i | |
j += 1 | |
end | |
return table | |
end | |
def kmp(string, pattern) | |
i = 0 | |
j = 0 | |
table = kmp_table(pattern) | |
results = [] | |
while true | |
while i < string.size and j < pattern.size | |
if string[i] == pattern[j] | |
i += 1 | |
j += 1 | |
elsif j > 0 | |
j = table[j - 1] | |
else | |
i += 1 | |
end | |
end | |
break if j != pattern.size | |
results << i - j | |
j = table[j - 1] | |
end | |
return results | |
end | |
begin | |
require 'bundler/inline' | |
rescue LoadError => e | |
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' | |
raise e | |
end | |
require 'minitest/autorun' | |
require 'logger' | |
class KmpTest < Minitest::Test | |
def test_multiple_match | |
assert_equal [4, 14, 22, 37], kmp('cozacocacolacococacolacocacoladjejdeicocacola', 'cocacola') | |
end | |
def test_not_match | |
assert_equal [], kmp('How do you do? Great thanks!', 'potato') | |
end | |
def test_overlapping_matches | |
assert_equal [0, 8, 19], kmp('aaabbbbaaaabbbbaaaaaaabbbbaaaa', 'aaabbbbaaaa') | |
end | |
def test_small_repeative_pattern | |
assert_equal [0, 2, 4, 8, 10, 12], kmp('abababaaabababaaab', 'aba') | |
assert_equal [6, 14], kmp('abababaaabababaaaba', 'aaab') | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment