algo : trouver le nombre le 'pattern' le plus frequent
|
05-12-2012, 19h38
Message : #1
|
|
gruik
gouteur de savon Messages : 757 Sujets : 44 Points: 482 Inscription : Oct 2012 |
algo : trouver le nombre le 'pattern' le plus frequent
le problème est assez simple finalement, et trouve de nombreuses applications, on peut citer par exemple la methode babbage-kasiski permettant de déterminer la longueur de la clé en cryptanalyse
la question est plus généraliste encore, disons qu'on a une liste d'items [a,a,a,a,b,c,d,a,a,d,a,b,d,d,c,b,a,d,c,a,c,d,d,b,a,a,b,b,a,d,a,a,b,c,d,d,c,a,b,c,d], on pourrait aussi bien voir ça comme un texte/une suite de mots ou une suite de lettres, peu importe le propos est de trouver la suite d'items la plus longue qui revient le plus fréquemment, comprenez qu'entre "a,a" qui fait 2 items de long et revient 6 fois, on préfèrera donner la priorité au pattern "a,b,c,d" qui fait 4 éléments de long et revient seulement 4 fois la question est simple, est-ce vous avez des idées de comment je pourrais implémenter ça, si possible de manière relativement efficace ? |
|
05-12-2012, 20h05
(Modification du message : 05-12-2012, 20h18 par InstinctHack.)
Message : #2
|
|
InstinctHack
Posting Freak Messages : 1,366 Sujets : 184 Points: 299 Inscription : Dec 2011 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Fonctionnel
Code PHP : function test($array) EDIT j'ai du mal en ce moment.... là je trouve la longueur du pattern de longueur 1 le long.... Faudrais juste générer les différents pattern possible, et rechercher le nomber d'occurence de chacun. Je continuerais avec plaisir demain Citation :un jour en cours de java j'ai attrapé les seins d'une fille mais elle m'a frappé en disant "c'est privé !!" |
|
05-12-2012, 20h33
(Modification du message : 05-12-2012, 20h34 par gruik.)
Message : #3
|
|
gruik
gouteur de savon Messages : 757 Sujets : 44 Points: 482 Inscription : Oct 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
ton code si je comprends bien retourne la longueur de la plus grande suite d'un meme item (genre pour "g,g,g,g,g,g,g,g" il retournera 8)
(donc pas bon, c'est pas ça l'objectif ) |
|
05-12-2012, 20h57
Message : #4
|
|
lesk8vaincra
Newbie Messages : 7 Sujets : 2 Points: 0 Inscription : Dec 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Pour proposer un algo faudrait que tu nous dises déja quelle est la règle "générale" pour décider qu'une plus longue suite est préférable.
longueur 4 * 4 est préférable a 6 *2 , mais est ce que 4 * 2 l'est aussi? En dehors de ca, ca me parait pas bien compliqué, tu fais une boucle qui parcoure ta chaine (ou ton fichier, ou...) et qui compte le nombre d'occurence d'une séquence (a l'aide, par exemple, d'une HashMap<String, int> en java?). Sinon, a mon sens: - une boucle de 2 a chaine.length()/2 pour établir la "longueur" des séquences a comparer. A la première itération, on chercher les séquences de longueur 2, puis de longueur 3,... - une boucle qui "avance" dans la chaine |
|
05-12-2012, 21h56
(Modification du message : 05-12-2012, 21h59 par b0fh.)
Message : #5
|
|
b0fh
Membre actif Messages : 210 Sujets : 17 Points: 309 Inscription : Jul 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Oui en effet, il faut donner un ordre meilleur que "la plus longue chaine", parce que sinon il suffit de prendre la chaîne entière, elle n'apparait qu'une fois mais c'est la plus longue.
Est-ce que (longueur de la sous-chaine) * (occurrences - 1) te parait une bonne métrique ? Il faut aussi définir si la chaine répétée peut se chevaucher. Si oui, aller jusqu'a longueur/2 n'est pas suffisant; par exemple avec "ababab" la meilleure sous-chaine est probablement"abab" Est-ce qu'une heuristique serait acceptable ? si oui, l'algorithme de Lempel-Ziv donnera peut-être de bons résultats. Est-ce que la chaine en entrée a des propriétés statistiques particulières ? si chaque caractère est distribué indépendamment, on peut probablement prédire la longueur approximative de la meilleure chaine ? Sinon, les solutions proposées sont en O(N^2), ce qui n'est pas "raisonnablement efficace" à mon sens. Je crois qu'une technique légèrement plus efficace serait de faire un tri externe des suffixes du tableau, puis de chercher dans ce tableau la meilleure séquence. Je fais une implémentation en haskell tout a l'heure |
|
05-12-2012, 22h10
(Modification du message : 05-12-2012, 22h24 par gruik.)
Message : #6
|
|
gruik
gouteur de savon Messages : 757 Sujets : 44 Points: 482 Inscription : Oct 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
(05-12-2012, 20h57)lesk8vaincra a écrit : longueur 4 * 4 est préférable a 6 *2 , mais est ce que 4 * 2 l'est aussi? nop, 6*2 est préférable aux deux autres justement la longueur est le premier discriminant (donc ca revient à chercher le motif répété au moins une fois le plus long possible), et ensuite seulement le nombre d'occurences est discriminant Citation :En dehors de ca, ca me parait pas bien compliqué, tu fais une boucle qui parcoure ta chaine (ou ton fichier, ou...) et qui compte le nombre d'occurence d'une séquence oui c'est tout le propos, mais l'approche naïve là dessus ça peut à mon avis rapidement s’avérer couteux, tout dépend la longueur de liste initiale (son nombre d'items, ou de lettre si on parle d'un texte), sachant que la "profondeur de recherche" ira d'un pattern de longueur len(liste_initiale)/2 comme tu le fais remarquer à un pattern de longueur 1 item en fait en y réfléchissant là je me dit qu'il y a surement à préciser également la question des patterns identiques "superposés", le cas où l'on a par exemple "a,b,c,d,a,b,c,d,a,b", le pattern le plus long serait donc "a,b,c,d,a,b", avec les deux derniers items "a,b" qui sont également le début du second pattern identique on a qu'à dire que ce point-ci est libre, comprendre qu'avec ou sans superposition je suis de toutes façons preneur, sachant que sans superposition ça s'optimise forcément plus vite du coup ( édith: le temps que je poste je n'avais pas lu ton message b0fh ) (05-12-2012, 21h56)b0fh a écrit : Est-ce qu'une heuristique serait acceptable ? si oui, l'algorithme de Lempel-Ziv donnera peut-être de bons résultats. posons que non, je jetterais quand même un oeil à Lempel-Ziv histoire de pas mourir idiot Citation :Est-ce que la chaine en entrée a des propriétés statistiques particulières ? là encore on va partir du principe que non, mais je garde l'idée dans un coin Citation :Je crois qu'une technique légèrement plus efficace serait de faire un tri externe des suffixes du tableau, puis de chercher dans ce tableau la meilleure séquence. je t'avoues tu me colles là, qu'est-ce que tu appelles "tri externe" et "suffixes" ? ^^ |
|
05-12-2012, 22h32
(Modification du message : 05-12-2012, 22h36 par lesk8vaincra.)
Message : #7
|
|
lesk8vaincra
Newbie Messages : 7 Sujets : 2 Points: 0 Inscription : Dec 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Bon jviens de me lancer dans un ptit code, testé mais pas forcémment parfaitement fonctionnel ou même optimisé, je ne veut absolument pas prétendre qu'il te conviendra mais ca pourrait te fournir d'éventuelles pistes:
Code : /* Les fonctions regexOccur et StringOccur ont été trouvées la: http://www.developpez.net/forums/d183810...ce-string/ A toi d'implémenter la méthode pour déterminer quelle est la meilleure sous-chaine a choisir en fonction de sa longueur et de sa fréquence. |
|
05-12-2012, 22h34
(Modification du message : 05-12-2012, 23h56 par b0fh.)
Message : #8
|
|
b0fh
Membre actif Messages : 210 Sujets : 17 Points: 309 Inscription : Jul 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Alors dans ton exemple premier, la plus longue chaine serait plutôt "aabcd" qui se répète deux fois.
Si tu considères que c'est correct, une implémentation O(n log n) en Haskell: Code : {-# LANGUAGE NoMonomorphismRestriction #-} Explications: "tails" crée la liste de tous les suffixes (çad les n derniers caractères, pour n de 1 à la longueur de la chaine). En Haskell prendre la queue d'une liste ne cause pas de réallocation, en C tu pourrais faire pareil en remplissant simplement un tableau de pointeurs vers chaque début possible de la string. Ce tableau est ensuite trié (tri externe veut dire qu'on trie des pointeurs vers des blogs de données potentiellement beaucoup plus gros, et qu'on évite le cout du déplacement ou du fetch complet desdonnées.) Ton plus long préfixe répété sera donc forcément sur deux lignes contigues. On considère chaque couple de ligne contigues (le zipWith <*> tails) en y appliquant commonPrefix (qui cherche le plus long préfixe commun possible). On prend les préfixes résultants, on les trie par longueur, et on prend le plus long. Si tu veux un critère arbitraire sur la longueur et le nombre de répétitions, tu pourrais placer tous ces préfixes dans un Patricia Tree puis parcourir l'arbre en calculant une métrique quelconque sur chaque noeud. |
|
07-12-2012, 16h42
(Modification du message : 08-12-2012, 18h10 par gruik.)
Message : #9
|
|
gruik
gouteur de savon Messages : 757 Sujets : 44 Points: 482 Inscription : Oct 2012 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
ok la logique ne m'a pas tout de suite sauté aux yeux et je vais me fendre d'une petite explication au cas où d'autres seraient à la fois intéressés et dans le gaz niveau compréhension
prenons la chaine "abracadabra" (oui je sais c'est pas terriblement original, c'est ni plus ni moins le même exemple que sur wikipedia) cette chaine compte donc 11 suffixes : Code : 1 abracadabra l'idée ça va être de comparer ces suffixes deux à deux pour trouver leur plus long préfixe commun de fait si on compare par exemple les suffixes "dabra" et "bra", ils ne commencent déjà pas par la même lettre, donc ça nous emmènera pas loin on va donc, avant de les comparer, trier les suffixes (par ordre alphanumérique croissant), du coup on se retrouve avec : Code : a partant de là - et c'est effectivement plus clair en le voyant - on est sûr que le plus long préfixe commun sera trouvé entre deux suffixes adjacents, puisque grâce au tri ceux qui se ressemblent sont déjà les uns à coté des autres, voyez l'idée ? reste à appliquer une recherche du plus long préfixe commun entre deux suffixes adjacents n et n+1, de ('a','abra') jusqu'à ('ra','racadabra') là, pour chaque couple de suffixe on va tout simplement matcher chaque lettre une à une en bouclant jusqu'à la fin du mot le plus court, pour à la fin retourner le plus long préfixe commun des deux suffixes on se retrouve alors avec une liste de préfixes comme celle là : Code : 'a' reste juste à prendre le plus long and voila, la plus longue sous-chaine répétée dans "abracadabra" c'est bien "abra" une implémentation simple (comprenez "qui vautre toute la ram en quelques seconde si la chaine est trop grande mais est suffisamment didactique et fera bien le job pour analyser quelques milliers de caractères") en python : Code PYTHON :
Code PYTHON :
reste la question de l'efficacité, comme disait b0fh en stockant des pointeurs pour créer son tableau de suffixes plutôt qu'en créant à chaque fois une copie en mémoire on évite d'exploser la ram, ce que semble permettre automatiquement Haskell mais en python le slicing chaine[x:y] occasionne obligatoirement une copie (que ce soit une chaine ou une liste d'ailleurs), affaire à suivre donc... EDIT: finalement en remplacant le slice chaine[i:] par buffer(chaine,i,None) on a bien ce qu'on veut sans le cout mémoire : Code DIFF :
Code PYTHON :
Code LIST :
|
|
07-12-2012, 21h27
Message : #10
|
|
Dobry
Tueur de lamouz Messages : 206 Sujets : 25 Points: 73 Inscription : Aug 2011 |
RE: algo : trouver le nombre le 'pattern' le plus frequent
Merci Gruik, en effet, les algos LCS sont très interessants et c'est un exemple qui s'y porte à merveille
Je sais pas pourquoi mais je bloque toujours avec ces algos (C++) je vais regarder ton code voir si finalement je bloquais pas sur quelque chose d'assez simple !
Aestuārium Erudītiōnis
There are only two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors.
|
|
« Sujet précédent | Sujet suivant »
|
Utilisateur(s) parcourant ce sujet : 5 visiteur(s)