



'''simple docstring'''





# Author: OMKAR PATHAK, Nwachukwu Chidiebere

# Use a Python dictionary to construct the graph.
from __future__ import annotations

from pprint import pformat
from typing import Generic, TypeVar

_lowerCAmelCase      						=	TypeVar('''T''')






class        lowerCAmelCase_(				Generic[T]     ):
  '''simple docstring'''




  def __init__(    self  ,__UpperCAmelCase = True      )    ->		None:
      lowerCAmelCase__ :  dict[T, list[T]]							      =					{}  # dictionary of lists
      lowerCAmelCase__ :  Optional[int]							      =					directed




  def 							UpperCAmelCase_	(    self  ,__UpperCAmelCase  ,__UpperCAmelCase      )    ->		GraphAdjacencyList[T]:

      if not self.directed:  # For undirected graphs
          # if both source vertex and destination vertex are both present in the
          # adjacency list, add destination vertex to source vertex list of adjacent
          # vertices and add source vertex to destination vertex list of adjacent
          # vertices.
          if source_vertex in self.adj_list and destination_vertex in self.adj_list:
              self.adj_list[source_vertex].append(__UpperCAmelCase      )
              self.adj_list[destination_vertex].append(__UpperCAmelCase      )
          # if only source vertex is present in adjacency list, add destination vertex
          # to source vertex list of adjacent vertices, then create a new vertex with
          # destination vertex as key and assign a list containing the source vertex
          # as it's first adjacent vertex.
          elif source_vertex in self.adj_list:
              self.adj_list[source_vertex].append(__UpperCAmelCase      )
              lowerCAmelCase__ :  List[str]							      =					[source_vertex]
          # if only destination vertex is present in adjacency list, add source vertex
          # to destination vertex list of adjacent vertices, then create a new vertex
          # with source vertex as key and assign a list containing the source vertex
          # as it's first adjacent vertex.
          elif destination_vertex in self.adj_list:
              self.adj_list[destination_vertex].append(__UpperCAmelCase      )
              lowerCAmelCase__ :  str							      =					[destination_vertex]
          # if both source vertex and destination vertex are not present in adjacency
          # list, create a new vertex with source vertex as key and assign a list
          # containing the destination vertex as it's first adjacent vertex also
          # create a new vertex with destination vertex as key and assign a list
          # containing the source vertex as it's first adjacent vertex.
          else:
              lowerCAmelCase__ :  List[Any]							      =					[destination_vertex]
              lowerCAmelCase__ :  str							      =					[source_vertex]
      else:  # For directed graphs
          # if both source vertex and destination vertex are present in adjacency
          # list, add destination vertex to source vertex list of adjacent vertices.
          if source_vertex in self.adj_list and destination_vertex in self.adj_list:
              self.adj_list[source_vertex].append(__UpperCAmelCase      )
          # if only source vertex is present in adjacency list, add destination
          # vertex to source vertex list of adjacent vertices and create a new vertex
          # with destination vertex as key, which has no adjacent vertex
          elif source_vertex in self.adj_list:
              self.adj_list[source_vertex].append(__UpperCAmelCase      )
              lowerCAmelCase__ :  List[str]							      =					[]
          # if only destination vertex is present in adjacency list, create a new
          # vertex with source vertex as key and assign a list containing destination
          # vertex as first adjacent vertex
          elif destination_vertex in self.adj_list:
              lowerCAmelCase__ :  List[str]							      =					[destination_vertex]
          # if both source vertex and destination vertex are not present in adjacency
          # list, create a new vertex with source vertex as key and a list containing
          # destination vertex as it's first adjacent vertex. Then create a new vertex
          # with destination vertex as key, which has no adjacent vertex
          else:
              lowerCAmelCase__ :  Dict							      =					[destination_vertex]
              lowerCAmelCase__ :  Optional[Any]							      =					[]

      return self






  def __repr__(    self      )    ->		str:
      return pformat(self.adj_list      )






'''simple docstring'''







from __future__ import annotations







class A__       :






      def __init__( self			:Union[str, Any]     ,						SCREAMING_SNAKE_CASE			:str     ,						SCREAMING_SNAKE_CASE			:str	)       ->					Optional[int]:




             '''simple docstring'''
             _a					,    _a    : List[str]     					=text, pattern
             _a					,    _a    : Union[str, Any]     					=len(SCREAMING_SNAKE_CASE	), len(SCREAMING_SNAKE_CASE	)






      def __UpperCAmelCase       ( self			:Optional[int]     ,						SCREAMING_SNAKE_CASE			:str	)       ->					int:




             '''simple docstring'''

             for i in range(self.patLen - 1     ,						-1     ,						-1	):
                    if char == self.pattern[i]:
                           return i
             return -1






      def __UpperCAmelCase       ( self			:Union[str, Any]     ,						SCREAMING_SNAKE_CASE			:int	)       ->					int:




             '''simple docstring'''

             for i in range(self.patLen - 1     ,						-1     ,						-1	):
                    if self.pattern[i] != self.text[current_pos + i]:
                           return current_pos + i
             return -1






      def __UpperCAmelCase       ( self			:Union[str, Any]	)       ->					list[int]:




             '''simple docstring'''
             # searches pattern in text and returns index positions
             _a    : Union[str, Any]     					=[]
             for i in range(self.textLen - self.patLen + 1	):
                    _a    : Any     					=self.mismatch_in_text(SCREAMING_SNAKE_CASE	)
                    if mismatch_index == -1:
                           positions.append(SCREAMING_SNAKE_CASE	)
                    else:
                           _a    : int     					=self.match_in_pattern(self.text[mismatch_index]	)
                           _a    : List[str]     					=(
                               mismatch_index - match_index
                           )  # shifting index lgtm [py/multiple-definition]
             return positions

A__:    Any					    =       '''ABAABA'''
A__:    int					    =       '''AB'''
A__:    Optional[int]					    =       BoyerMooreSearch(text, pattern)
A__:    Optional[Any]					    =       bms.bad_character_heuristic()

if len(positions) == 0:
   print('''No match found''')
else:
   print('''Pattern found in following positions: ''')
   print(positions)


