'Takes a list of strings and generates all character ngrams.
Generated ngrams are at least 3 characters (and at most 17), occur at least 5 times
and occur independently of longer superset ngrams at least once.'

def _generate_all_ngrams(self, list_of_strings):

    features = {}
    counters = {(self.n_gram_min_length - 1): Counter()}
    for n in range(self.n_gram_min_length, self.n_gram_max_length):
        candidates = []
        features[n] = []
        counters[n] = Counter()
        for text in list_of_strings:
            text = text.replace(punctuation, u'    ')
            for word in text.lower().split(u'    '):
                cands = [word[i:(i + n)] for i in range((len(word) - n))]
                for cand in cands:
                    counters[n][cand] += 1
                    if (cand not in candidates):
                        candidates.append(cand)
        for can in candidates:
            if (counters[n][can] >= self.n_gram_min_occurrences):
                features[n].append(can)
                begin = can[:(-1)]
                end = can[1:]
                if (n >= self.n_gram_min_length):
                    if ((counters[(n - 1)][begin] == counters[n][can]) and (begin in features[(n - 1)])):
                        features[(n - 1)].remove(begin)
                    if ((counters[(n - 1)][end] == counters[n][can]) and (end in features[(n - 1)])):
                        features[(n - 1)].remove(end)
    return [item for sublist in list(features.values()) for item in sublist]
