You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

46 lines
1.2 KiB
Ruby

# Knuth-Morris-Pratt Algorithm substring search algorithm: Efficiently finds the starting position of a
# substring in a string. The algorithm calculates the best position to resume searching from if a failure
# occurs.
#
# The method returns the index of the starting position in the string where the substring is found. If there
# is no match, nil is returned.
#
# Complexity: O(n + k), where n is the length of the string and k is the length of the substring.
#
# "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD") #=> 15
# "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDEF") #=> nil
class Array
def self.kmp_search(substring)
return nil if self.nil? or substring.nil?
pos = 2
cnd = 0
failure_table = [-1, 0]
while pos < substring.length
if substring[pos - 1] == substring[cnd]
failure_table[pos] = cnd + 1
pos += 1
cnd += 1
elsif cnd > 0
cnd = failure_table[cnd]
else
failure_table[pos] = 0
pos += 1
end
end
m = i = 0
while m + i < self.length
if substring[i] == self[m + i]
i += 1
return m if i == substring.length
else
m = m + i - failure_table[i]
i = failure_table[i] if i > 0
end
end
return nil
end
end