





'''simple docstring'''







from __future__ import annotations

from collections import deque


class 					__a      :

							def __init__(							self							:     List[Any]       ,     __magic_name__							:     list[str]   )					->       Union[str, Any]:







													"""simple docstring"""
													UpperCAmelCase_			:      list[dict]     						=  []
													self.adlist.append(
													    {'''value''': '''''', '''next_states''': [], '''fail_state''': 0, '''output''': []}   )

													for keyword in keywords:
																			self.add_keyword(__magic_name__   )
													self.set_fail_transitions()

							def     UpperCAmelCase__	(							self							:     str       ,     __magic_name__							:     int       ,     __magic_name__							:     str   )					->       int | None:







													"""simple docstring"""
													for state in self.adlist[current_state]["next_states"]:
																			if char == self.adlist[state]["value"]:
																									return state
													return None

							def     UpperCAmelCase__	(							self							:     Optional[int]       ,     __magic_name__							:     str   )					->       None:







													"""simple docstring"""
													UpperCAmelCase_			:      Tuple     						=  0
													for character in keyword:
																			UpperCAmelCase_			:      List[Any]     						=  self.find_next_state(__magic_name__       ,     __magic_name__   )
																			if next_state is None:
																									self.adlist.append(
																									    {
																									        '''value''': character,
																									        '''next_states''': [],
																									        '''fail_state''': 0,
																									        '''output''': [],
																									    }   )
																									self.adlist[current_state]["next_states"].append(len(self.adlist   ) - 1   )
																									UpperCAmelCase_			:      Optional[Any]     						=  len(self.adlist   ) - 1
																			else:
																									UpperCAmelCase_			:      Optional[Any]     						=  next_state
													self.adlist[current_state]["output"].append(__magic_name__   )

							def     UpperCAmelCase__	(							self							:     str   )					->       None:







													"""simple docstring"""
													UpperCAmelCase_			:      deque     						=  deque()
													for node in self.adlist[0]["next_states"]:
																			q.append(__magic_name__   )
																			UpperCAmelCase_			:      Any     						=  0
													while q:
																			UpperCAmelCase_			:      str     						=  q.popleft()
																			for child in self.adlist[r]["next_states"]:
																									q.append(__magic_name__   )
																									UpperCAmelCase_			:      str     						=  self.adlist[r]['''fail_state''']
																									while (
																									    self.find_next_state(__magic_name__       ,     self.adlist[child]['''value''']   ) is None
																									    and state != 0
																									):
																															UpperCAmelCase_			:      Tuple     						=  self.adlist[state]['''fail_state''']
																									UpperCAmelCase_			:      Union[str, Any]     						=  self.find_next_state(
																									    __magic_name__       ,     self.adlist[child]['''value''']   )
																									if self.adlist[child]["fail_state"] is None:
																															UpperCAmelCase_			:      List[Any]     						=  0
																									UpperCAmelCase_			:      Optional[Any]     						=  (
																									    self.adlist[child]['''output''']
																									    + self.adlist[self.adlist[child]['''fail_state''']]['''output''']
																									)



							def     UpperCAmelCase__	(							self							:     Optional[int]       ,     __magic_name__							:     str   )					->       dict[str, list[int]]:







													"""simple docstring"""
													UpperCAmelCase_			:      dict     						=  {}  # returns a dict with keywords and list of its occurrences
													UpperCAmelCase_			:      Optional[Any]     						=  0
													for i in range(len(__magic_name__   )   ):
																			while (
																			    self.find_next_state(__magic_name__       ,     string[i]   ) is None
																			    and current_state != 0
																			):
																									UpperCAmelCase_			:      Tuple     						=  self.adlist[current_state]['''fail_state''']
																			UpperCAmelCase_			:      List[Any]     						=  self.find_next_state(__magic_name__       ,     string[i]   )
																			if next_state is None:
																									UpperCAmelCase_			:      List[Any]     						=  0
																			else:
																									UpperCAmelCase_			:      Optional[int]     						=  next_state
																									for key in self.adlist[current_state]["output"]:
																															if key not in result:
																																					UpperCAmelCase_			:      Any     						=  []
																															result[key].append(i - len(__magic_name__   ) + 1   )
													return result


if __name__ == "__main__":
					import doctest

					doctest.testmod()












'''simple docstring'''







from collections.abc import Iterable
from typing import Any


class 					__a      :

							def __init__(							self							:     Optional[Any]       ,     __magic_name__							:     int | None = None   )					->       Tuple:







													"""simple docstring"""
													UpperCAmelCase_			:      List[str]     						=  value
													UpperCAmelCase_			:      Node | None     						=  None  # Added in order to delete a node easier
													UpperCAmelCase_			:      Node | None     						=  None
													UpperCAmelCase_			:      Node | None     						=  None



							def __repr__(							self							:     List[str]   )					->       str:







													"""simple docstring"""
													from pprint import pformat

													if self.left is None and self.right is None:
																			return str(self.value   )
													return pformat({F"""{self.value}""": (self.left, self.right)}       ,     indent=1   )





class 					__a      :

							def __init__(							self							:     int       ,     __magic_name__							:     Node | None = None   )					->       Optional[int]:







													"""simple docstring"""
													UpperCAmelCase_			:      str     						=  root

							def __str__(							self							:     Any   )					->       str:







													"""simple docstring"""
													return str(self.root   )

							def     UpperCAmelCase__	(							self							:     Any       ,     __magic_name__							:     Node       ,     __magic_name__							:     Node | None   )					->       None:







													"""simple docstring"""
													if new_children is not None:  # reset its kids
																			UpperCAmelCase_			:      Dict     						=  node.parent
													if node.parent is not None:  # reset its parent
																			if self.is_right(__magic_name__   ):  # If it is the right children
																									UpperCAmelCase_			:      Optional[Any]     						=  new_children
																			else:
																									UpperCAmelCase_			:      Optional[int]     						=  new_children
													else:
																			UpperCAmelCase_			:      List[str]     						=  new_children

							def     UpperCAmelCase__	(							self							:     List[str]       ,     __magic_name__							:     Node   )					->       bool:







													"""simple docstring"""
													if node.parent and node.parent.right:
																			return node == node.parent.right
													return False

							def     UpperCAmelCase__	(							self							:     Union[str, Any]   )					->       bool:







													"""simple docstring"""
													return self.root is None

							def     UpperCAmelCase__	(							self							:     Any       ,     __magic_name__							:     str   )					->       None:







													"""simple docstring"""
													UpperCAmelCase_			:      Tuple     						=  Node(__magic_name__   )  # create a new Node
													if self.empty():  # if Tree is empty
																			UpperCAmelCase_			:      List[Any]     						=  new_node  # set its root
													else:  # Tree is not empty
																			UpperCAmelCase_			:      str     						=  self.root  # from root
																			if parent_node is None:
																									return
																			while True:  # While we don't get to a leaf
																									if value < parent_node.value:  # We go left
																															if parent_node.left is None:
																																					UpperCAmelCase_			:      Union[str, Any]     						=  new_node  # We insert the new node in a leaf
																																					break
																															else:
																																					UpperCAmelCase_			:      List[Any]     						=  parent_node.left
																									else:
																															if parent_node.right is None:
																																					UpperCAmelCase_			:      List[Any]     						=  new_node
																																					break
																															else:
																																					UpperCAmelCase_			:      Union[str, Any]     						=  parent_node.right
																			UpperCAmelCase_			:      Union[str, Any]     						=  parent_node

							def     UpperCAmelCase__	(							self							:     Optional[Any]       ,     *__magic_name__							:     List[str]   )					->       None:







													"""simple docstring"""
													for value in values:
																			self.__insert(__magic_name__   )

							def     UpperCAmelCase__	(							self							:     Dict       ,     __magic_name__							:     int   )					->       Node | None:







													"""simple docstring"""
													if self.empty():
																			raise IndexError('''Warning: Tree is empty! please use another.'''   )
													else:
																			UpperCAmelCase_			:      str     						=  self.root
																			# use lazy evaluation here to avoid NoneType Attribute error
																			while node is not None and node.value is not value:
																									UpperCAmelCase_			:      List[str]     						=  node.left if value < node.value else node.right
																			return node

							def     UpperCAmelCase__	(							self							:     Optional[int]       ,     __magic_name__							:     Node | None = None   )					->       Node | None:







													"""simple docstring"""
													if node is None:
																			if self.root is None:
																									return None
																			UpperCAmelCase_			:      Dict     						=  self.root

													if not self.empty():
																			while node.right is not None:
																									UpperCAmelCase_			:      Any     						=  node.right
													return node

							def     UpperCAmelCase__	(							self							:     Dict       ,     __magic_name__							:     Node | None = None   )					->       Node | None:







													"""simple docstring"""
													if node is None:
																			UpperCAmelCase_			:      Optional[int]     						=  self.root
													if self.root is None:
																			return None
													if not self.empty():
																			UpperCAmelCase_			:      Union[str, Any]     						=  self.root
																			while node.left is not None:
																									UpperCAmelCase_			:      Dict     						=  node.left
													return node

							def     UpperCAmelCase__	(							self							:     Tuple       ,     __magic_name__							:     int   )					->       None:







													"""simple docstring"""
													UpperCAmelCase_			:      List[str]     						=  self.search(__magic_name__   )  # Look for the node with that label
													if node is not None:
																			if node.left is None and node.right is None:  # If it has no children
																									self.__reassign_nodes(__magic_name__       ,     __magic_name__   )
																			elif node.left is None:  # Has only right children
																									self.__reassign_nodes(__magic_name__       ,     node.right   )
																			elif node.right is None:  # Has only left children
																									self.__reassign_nodes(__magic_name__       ,     node.left   )
																			else:
																									UpperCAmelCase_			:      List[str]     						=  self.get_max(
																									    node.left   )  # Gets the max value of the left branch
																									self.remove(tmp_node.value   )  # type: ignore
																									UpperCAmelCase_			:      Optional[int]     						=  (
																									    tmp_node.value  # type: ignore
																									)  # Assigns the value to the node to delete and keep tree structure

							def     UpperCAmelCase__	(							self							:     List[Any]       ,     __magic_name__							:     Node | None   )					->       Iterable:







													"""simple docstring"""
													if node is not None:
																			yield node  # Preorder Traversal
																			yield from self.preorder_traverse(node.left   )
																			yield from self.preorder_traverse(node.right   )

							def     UpperCAmelCase__	(							self							:     List[Any]       ,     __magic_name__							:     List[Any]=None   )					->       Any:







													"""simple docstring"""
													if traversal_function is None:
																			return self.preorder_traverse(self.root   )
													else:
																			return traversal_function(self.root   )

							def     UpperCAmelCase__	(							self							:     Optional[int]       ,     __magic_name__							:     list       ,     __magic_name__							:     Node | None   )					->       None:







													"""simple docstring"""
													if node:
																			self.inorder(__magic_name__       ,     node.left   )
																			arr.append(node.value   )
																			self.inorder(__magic_name__       ,     node.right   )



							def     UpperCAmelCase__	(							self							:     Tuple       ,     __magic_name__							:     int       ,     __magic_name__							:     Node   )					->       int:







													"""simple docstring"""
													UpperCAmelCase_			:      list[int]     						=  []
													self.inorder(__magic_name__       ,     __magic_name__   )  # append all values to list using inorder traversal
													return arr[k - 1]





def        lowerCamelCase_      (  SCREAMING_SNAKE_CASE__      :			Node | None   ) ->	list[Node]:
						UpperCAmelCase_			:      Any     						=  []
						if curr_node is not None:
												UpperCAmelCase_			:      Any     						=  postorder(curr_node.left   ) + postorder(curr_node.right   ) + [curr_node]
						return node_list





def        lowerCamelCase_      (  ) ->	None:
						UpperCAmelCase_			:      str     						=  (8, 3, 6, 1, 10, 14, 13, 4, 7)
						UpperCAmelCase_			:      Tuple     						=  BinarySearchTree()
						for i in testlist:
												t.insert(SCREAMING_SNAKE_CASE__   )

						# Prints all the elements of the list in order traversal
						print(SCREAMING_SNAKE_CASE__   )

						if t.search(6   ) is not None:
												print('''The value 6 exists'''   )
						else:
												print('''The value 6 doesn\'t exist'''   )

						if t.search(-1   ) is not None:
												print('''The value -1 exists'''   )
						else:
												print('''The value -1 doesn\'t exist'''   )

						if not t.empty():
												print('''Max Value: ''',			t.get_max().value   )  # type: ignore
												print('''Min Value: ''',			t.get_min().value   )  # type: ignore

						for i in testlist:
												t.remove(SCREAMING_SNAKE_CASE__   )
												print(SCREAMING_SNAKE_CASE__   )


if __name__ == "__main__":
					import doctest

					doctest.testmod(verbose=True)





