46 lines
1.2 KiB
Ruby
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 |