code: def return_max_phrase(run, idx, dictionary):
          
          if idx < len(run) and run[idx] in dictionary:
              id = run[idx]
              rv, rv_idx = PhraseDictionary.return_max_phrase(run, idx + 1, dictionary[id])
              if rv is not None:
                  return rv, rv_idx
  
          if None in dictionary:
              return dictionary[None], idx
          else:
              return None, None
docs: Finds the maximal phrase in the run starting from the given index.  It uses the dictionary to find sequences of ids
           that can be merged into a phrase.
          :param run: a run of ids
          :param idx: the position in the run to start looking for a merge sequence
          :param dictionary: the dictionary to use to determine if a merge id is present.  This should be a dictionary of
          dictionaries.  Each inner dictionary is a continuation of a mergable run.  The end of a run is donated by a None key
          in a dictionary.  The value associated with the None key is the integer of the merge id.
          :return: phrase_id or None, index after the phrase_id or the current index if no phrase was found.