Skip to content

Commit 79ffaec

Browse files
Fix Boyer-Moore bad character shift having no effect
The bad_character_heuristic() reassigned the for-loop variable i inside the loop body, which has no effect on iteration in Python. As a result the bad-character shift was dead code and the search degenerated into brute-force O(n*m) checking every position, while still claiming O(n/m) in the module docstring. Convert the loop to a while loop so the shift actually applies, guaranteeing at least one position of progress per iteration via max(i + 1, mismatch_index - match_index). Verified: all doctests pass, 2000 randomized comparisons against brute-force search pass, and the example from the issue now takes 9 iterations instead of 29. Fixes #14844
1 parent f5988cc commit 79ffaec

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

strings/boyer_moore_search.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,18 @@ def bad_character_heuristic(self) -> list[int]:
8686
"""
8787

8888
positions = []
89-
for i in range(self.textLen - self.patLen + 1):
89+
i = 0
90+
while i <= self.textLen - self.patLen:
9091
mismatch_index = self.mismatch_in_text(i)
9192
if mismatch_index == -1:
9293
positions.append(i)
94+
i += 1
9395
else:
9496
match_index = self.match_in_pattern(self.text[mismatch_index])
95-
i = (
96-
mismatch_index - match_index
97-
) # shifting index lgtm [py/multiple-definition]
97+
# shift pattern so the last occurrence of the mismatched
98+
# character in the pattern aligns with the text, while
99+
# always making at least one position of progress
100+
i = max(i + 1, mismatch_index - match_index)
98101
return positions
99102

100103

0 commit comments

Comments
 (0)