



'''simple docstring'''






from __future__ import annotations

from collections import deque



class 							lowercase       :


 """simple docstring"""


 def __init__(							self  ,a_							)		->   Optional[Any]:
        _UpperCAmelCase  :						list[dict]			     = []
        self.adlist.append(
            {"""value""": """""", """next_states""": [], """fail_state""": 0, """output""": []}							)

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







 def _snake_case (							self  ,a_  ,a_							)		->   int | None:
        for state in self.adlist[current_state]["next_states"]:
               if char == self.adlist[state]["value"]:
                      return state
        return None







 def _snake_case (							self  ,a_							)		->   None:
        _UpperCAmelCase  :						List[Any]			     = 0
        for character in keyword:
               _UpperCAmelCase  :						Optional[Any]			     = self.find_next_state(a_  ,a_							)
               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  :						Union[str, Any]			     = len(self.adlist							) - 1
               else:
                      _UpperCAmelCase  :						Any			     = next_state
        self.adlist[current_state]["output"].append(a_							)







 def _snake_case (							self							)		->   None:
        _UpperCAmelCase  :						deque			     = deque()
        for node in self.adlist[0]["next_states"]:
               q.append(a_							)
               _UpperCAmelCase  :						Optional[int]			     = 0
        while q:
               _UpperCAmelCase  :						List[str]			     = q.popleft()
               for child in self.adlist[r]["next_states"]:
                      q.append(a_							)
                      _UpperCAmelCase  :						Dict			     = self.adlist[r]["""fail_state"""]
                      while (
                          self.find_next_state(a_  ,self.adlist[child]["""value"""]							) is None
                          and state != 0
                      ):
                             _UpperCAmelCase  :						Dict			     = self.adlist[state]["""fail_state"""]
                      _UpperCAmelCase  :						Optional[Any]			     = self.find_next_state(
                          a_  ,self.adlist[child]["""value"""]							)
                      if self.adlist[child]["fail_state"] is None:
                             _UpperCAmelCase  :						List[Any]			     = 0
                      _UpperCAmelCase  :						int			     = (
                          self.adlist[child]["""output"""]
                          + self.adlist[self.adlist[child]["""fail_state"""]]["""output"""]
                      )







 def _snake_case (							self  ,a_							)		->   dict[str, list[int]]:
        _UpperCAmelCase  :						dict			     = {}  # returns a dict with keywords and list of its occurrences
        _UpperCAmelCase  :						Dict			     = 0
        for i in range(len(a_							)							):
               while (
                   self.find_next_state(a_  ,string[i]							) is None
                   and current_state != 0
               ):
                      _UpperCAmelCase  :						List[Any]			     = self.adlist[current_state]["""fail_state"""]
               _UpperCAmelCase  :						List[Any]			     = self.find_next_state(a_  ,string[i]							)
               if next_state is None:
                      _UpperCAmelCase  :						int			     = 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(a_							) + 1							)
        return result


if __name__ == "__main__":
   import doctest

   doctest.testmod()








'''simple docstring'''






# using dfs for finding eulerian path traversal




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_=None		)->		List[str]:





       '''simple docstring'''


       _UpperCAmelCase  :						Any			     = (path or []) + [u]
       for v in graph[u]:
              if visited_edge[u][v] is False:
                     _UpperCAmelCase     ,_UpperCAmelCase  :						Tuple			     = True, True
                     _UpperCAmelCase  :						List[Any]			     = dfs(lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_		)
       return path




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_		)->		Optional[int]:





       '''simple docstring'''


       _UpperCAmelCase  :						Optional[Any]			     = 0
       _UpperCAmelCase  :						Optional[int]			     = -1
       for i in range(lowerCAmelCase_		):
              if i not in graph.keys():
                     continue
              if len(graph[i]		) % 2 == 1:
                     odd_degree_nodes += 1
                     _UpperCAmelCase  :						Optional[int]			     = i
       if odd_degree_nodes == 0:
              return 1, odd_node
       if odd_degree_nodes == 2:
              return 2, odd_node
       return 3, odd_node




def     snake_case_					(     lowerCAmelCase_       ,   lowerCAmelCase_		)->		List[Any]:





       '''simple docstring'''


       _UpperCAmelCase  :						str			     = [[False for _ in range(max_node + 1		)] for _ in range(max_node + 1		)]
       _UpperCAmelCase     ,_UpperCAmelCase  :						int			     = check_circuit_or_path(lowerCAmelCase_       ,   lowerCAmelCase_		)
       if check == 3:
              print("""graph is not Eulerian"""		)
              print("""no path"""		)
              return
       _UpperCAmelCase  :						Dict			     = 1
       if check == 2:
              _UpperCAmelCase  :						Dict			     = odd_node
              print("""graph has a Euler path"""		)
       if check == 1:
              print("""graph has a Euler cycle"""		)
       _UpperCAmelCase  :						Dict			     = dfs(lowerCAmelCase_       ,   lowerCAmelCase_       ,   lowerCAmelCase_		)
       print(lowerCAmelCase_		)




def     snake_case_					(     )->		Union[str, Any]:





       '''simple docstring'''


       _UpperCAmelCase  :						Any			     = {1: [2, 3, 4], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [4]}
       _UpperCAmelCase  :						int			     = {1: [2, 3, 4, 5], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [1, 4]}
       _UpperCAmelCase  :						Tuple			     = {1: [2, 3, 4], 2: [1, 3, 4], 3: [1, 2], 4: [1, 2, 5], 5: [4]}
       _UpperCAmelCase  :						List[Any]			     = {1: [2, 3], 2: [1, 3], 3: [1, 2]}
       _UpperCAmelCase  :						List[str]			     = {
           1: [],
           2: []
           # all degree is zero
       }
       _UpperCAmelCase  :						Union[str, Any]			     = 10
       check_euler(lowerCAmelCase_       ,   lowerCAmelCase_		)
       check_euler(lowerCAmelCase_       ,   lowerCAmelCase_		)
       check_euler(lowerCAmelCase_       ,   lowerCAmelCase_		)
       check_euler(lowerCAmelCase_       ,   lowerCAmelCase_		)
       check_euler(lowerCAmelCase_       ,   lowerCAmelCase_		)


if __name__ == "__main__":
   main()



