2015-08-21 3 views
1

Je cherche à renvoyer la meilleure correspondance d'une liste par rapport à une collection de listes.Correspondance par rapport à la plus longue sous-chaîne

x correspond à une liste de la collection si la liste de la collection de longueur n correspond aux n premiers éléments de x.

par exemple. [1,2,3] correspond à [1,2] mais [1,2] ne correspond pas à [1,2,3].

Je souhaite que la fonction renvoie la "meilleure" correspondance, c'est-à-dire la correspondance la plus longue.

par exemple.

bestMatch [1,2,3,3] [[1],[1,2,3],[1,2],[1,2,3,2],[1,2,3,4]] == Just [1,2,3] 

Il est évident que la liste n'est pas ici la meilleure structure de données, et je préfère utiliser une structure standard et la recherche plutôt que rouler mes propres idées, ce que je devrais utiliser et comment?

Je ne pense pas que les tables de hachage fonctionneront parce que les correspondances ne sont pas exactes. J'ai alors pensé à la recherche contre un arbre ordonné, mais il a le problème que si je recherche [1,2,100], j'obtiendrai [1,2,99], [1,2,98], ... etc avant d'obtenir la bonne réponse, [1,2]. Pourrait utiliser un hachage de hachages (et ainsi de suite dans l'arbre), mais cela semble être beaucoup de frais généraux.

(Une liste de recherche linéaire mise en œuvre est basée here)

+3

Un Trie semble approprié. –

+1

Y a-t-il une raison pour laquelle vous fournissez seulement un lien vers le code et non le code directement dans la question? Pour moi, il semble que vous ne faites que nuire à la facilité de copier-coller et de surligner (l'ideone se trompe) ... un lien vers ideone peut être utile mais je ne vois aucune raison de ne pas coller le code * aussi * dans la question. – Bakuriu

+0

BTW vous vous trompez sur l'arbre ordonné, vous n'avez pas à vérifier autant d'éléments. Si '[1,1] .. [1,100] et [2,1] .. [2,100]' sont dans l'arbre, alors pour arriver '[2,1]', il faudrait vérifier, disons ' [1,100] ',' [2,50] ',' [2,25] ',' [2,12] ',' [2,6] ',' [2,3] ',' [2,1 ] '- c'est-à-dire un nombre logarithmique d'éléments. C'est en général assez rapide: le logarithme d'un milliard n'a que 30 ans. Je suis d'accord avec Nico pour dire qu'un trie semble parfait - alors vous pouvez même avoir un nombre infini d'éléments! :-) – luqui

Répondre

3

A serait Trie une bonne solution. Dans votre cas, les valeurs seraient simplement (), indiquant qu'un nœud donné correspond à une fin de liste. Ensuite, si vous avez une liste, vous allez juste parcourir le trie le plus bas possible, et la dernière valeur rencontrée marquera la liste la plus longue.

A ByteString base Trie en Data.Trie offre match, qui semble être exactement ce que vous cherchez (si les clés seraient suffisantes pour vous CHARS 8 octets):

-- | Given a query, find the longest prefix with an associated value in 
-- the trie, returning that prefix, it's value, and the remaining string. 
match :: Trie a -> ByteString -> Maybe (ByteString, a, ByteString) 

Il y a aussi un autre paquet list-tries, qui a des clés plus génériques. Je ne suis pas sûr s'il y a une fonction exacte comme match ci-dessus, mais certainement il serait possible d'en implémenter un.