mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-02-03 08:46:02 +01:00
60 lines
1.8 KiB
Ruby
60 lines
1.8 KiB
Ruby
##
|
|
# This class represents a table of {bad_match_character => slide_offset}
|
|
# to be used in Boyer-Moore-Horspool substring finding algorithm.
|
|
|
|
class BadMatchTable
|
|
|
|
attr_reader :pattern
|
|
attr_reader :table
|
|
|
|
def initialize(pattern)
|
|
@pattern = pattern
|
|
@table = {}
|
|
for i in 0...pattern.size
|
|
@table[pattern[i]] = pattern.size - 1 - i
|
|
end
|
|
end
|
|
|
|
##
|
|
# Given a mismatch character belonging to the search string, returns
|
|
# the offset to be used when sliding the pattern towards the right.
|
|
|
|
def slide_offset(mismatch_char)
|
|
table.fetch(mismatch_char, pattern.size)
|
|
end
|
|
end
|
|
|
|
##
|
|
# Returns the first starting index of the given pattern's occurrence (as a substring)
|
|
# in the provided search string if a match is found, -1 otherwise.
|
|
|
|
def first_match_index(search_string, pattern)
|
|
matches = matches_indices(search_string, pattern, true)
|
|
matches.empty? ? -1 : matches[0]
|
|
end
|
|
|
|
##
|
|
# Returns the list of starting indices of the given pattern's occurrences (as a substring)
|
|
# in the provided search string.
|
|
# If no match is found, an empty list is returned.
|
|
# If `stop_at_first_match` is provided as `true`, the returned list will contain at most one element,
|
|
# being the leftmost encountered match in the search string.
|
|
|
|
def matches_indices(search_string, pattern, stop_at_first_match=false)
|
|
table = BadMatchTable.new(pattern)
|
|
i = pattern.size - 1
|
|
indices = []
|
|
while i < search_string.size
|
|
for j in 0...pattern.size
|
|
if search_string[i-j] != pattern[pattern.size-1-j]
|
|
i += table.slide_offset(search_string[i-j])
|
|
break
|
|
elsif j == pattern.size-1
|
|
indices.append(i-j)
|
|
return indices if stop_at_first_match
|
|
i += 1
|
|
end
|
|
end
|
|
end
|
|
indices
|
|
end
|