Хорошо, я собираюсь предложить что-то странное, но исходя из C++
Я давно пользуюсь Boost
, и я пришел к библиотеке MultiIndex
.
Идея этой библиотеки состоит в том, чтобы создать одну коллекцию, но есть много разных способов ее запросить. Фактически он может моделировать базу данных.
Итак, давайте поместим наши слова в таблицу и разместим необходимые индексы:
word |length|c0|c1|c2| ... |c26|
-------------------------|------|--|--|--| ... |---|
Singapour |9 |S |i |n | ... |0 |
Теперь запрос будет выглядеть так:
Select word From table Where length=9 And c2='n' And c8='u';
Достаточно просто, не правда ли?
Для максимальной эффективности таблица должна быть секционирована по длине, а индексы (по одному на столбец cX) должны быть локальными по отношению к разделу.
Для решения в памяти у вас будет один контейнер на длину, содержащий столько индексов, сколько длина, причем каждый индекс представляет собой хеш-таблицу, указывающую на отсортированный список (более простое объединение)
Вот описание питона:
class Dictionary:
def __init__(self, length):
self.length = length
self.words = set([])
self.indexes = collections.defaultdict(set)
def add(self, word):
if len(word) != self.length:
raise RuntimeException(word + ' is not ' + `self.length` + ' characters long')
if word in self.words:
raise RuntimeException(word + ' is already in the dictionary')
self.words.add(word)
for i in range(0,length):
self.indexes[(i,word[i])].add(word)
def search(self, list):
"""list: list of tuples (position,character)
"""
def compare(lhs,rhs): return cmp(len(lhs),len(rhs))
sets = [self.indexes[elem] for elem in list]
sets.sort(compare)
return reduce(intersection, sets)
Я добровольно предоставил аргумент length
, чтобы минимизировать размер хэшей и тем самым улучшить поиск. Кроме того, наборы сортируются по длине, чтобы вычисление пересечения было лучше:)
Если хотите, протестируйте его с другими решениями:)