def get_tags(train_dict: dict,
             sentence: list,
             lowercase: bool = False) -> list:
    """Greedy approach that looks for tags starting at each token position in the sentence
     and extends the window size one at a time up to a maximum size of max_key_len. If an 
     entity is found in the train_dict, the token read position advances past the found entity
     and continues looking for entities, else the read position advances by one.

    Args:
        train_dict (dict): Dictionary with entities as keys and tags as values, e.g. {('Washington', 'DC'): 'LOC', ...}.
        sentence (list): Tokenized sentence to tag.
        lowercase (bool, optional): Optionally lowercase tokens before looking up entities in train_dict. Defaults to False.

    Returns:
        list: Tagged sentence, which is a list of tuples, e.g. [('Washington', 'LOC'), ('DC', 'LOC'), ('is', 'O), ...].
    """
    # get max key length to limit the search window
    max_key_len = max([len(x) for x in list(train_dict.keys())])

    labeled_sentence = [('<placeholder>', 'O')] * len(sentence)
    i = 0
    while i != len(sentence):
        broke = False
        for j in range(1, max_key_len):
            end_index = min(i + j, len(sentence))
            # optionally lower case when looking up in train_dict
            if lowercase:
                lowercase_sub_sentence = [
                    x.lower() for x in sentence[i:end_index]
                ]
                sub_sentence = tuple(lowercase_sub_sentence)
            else:
                sub_sentence = tuple(sentence[i:end_index])

            if sub_sentence in train_dict:
                entity_type = train_dict[sub_sentence]
                tags = [(tok, entity_type) for tok in sentence[i:end_index]]
                labeled_sentence[i:end_index] = tags
                i += j
                broke = True
                break
            else:
                tags = [(tok, 'O') for tok in sentence[i:end_index]]
                labeled_sentence[i:end_index] = tags
        # if nothing found
        if not broke:
            i += 1
    return labeled_sentence