from typing import Dict def make_km_table(pattern: str) -> Dict[str, int]: PATTERN_LENGTH = len(pattern) table = {} for index_from_left, char in enumerate(pattern[:-1]): table[char] = PATTERN_LENGTH - index_from_left - 1 return table class Bm(object): def __init__(self, text: str, pattern: str): self.text = text self.pattern = pattern self.table = make_km_table(pattern) def decide_slide_width(self, c: str) -> int: try: return self.table[c] except KeyError: return len(self.pattern) def search(self) -> int: PATTERN_LENGTH = len(self.pattern) head = PATTERN_LENGTH - 1 while head < len(self.text): if self.text[head] == self.pattern[-1]: for index_from_right, char in enumerate(reversed(self.pattern)): if self.text[head - index_from_right] != char: head += self.decide_slide_width(self.text[head]) break else: return head - PATTERN_LENGTH + 1 else: head += self.decide_slide_width(self.text[head]) return -1