8
votes

Trouver une chaîne * et * ses sous-chaînes dans une botte de foin

Supposons que vous ayez une chaîne (E.G. aiguille code>). Ses 19 sous-chaînes continues sont les suivantes:

/(needle|needl|eedle|need|eedl|edle|nee|eed|edl|dle)/


6 commentaires

Cela ressemble beaucoup à la Substring commun le plus long problème. A-t-il besoin d'être regexp?


La longueur de l'aiguille sera sûrement des ordres de grandeur plus petites que celle de la botte de foin. De plus, je suis intéressé à savoir combien d'occurrences de l'une des sous-chaînes de l'aiguille apparaissent dans la botte de foin, et non celle de la LCS.


Je ne pense pas que cet événement une question de loin plus simple ( Stackoverflow.com/questions/9114402/... ) a une solution facile en utilisant une regexp afin que vous devriez probablement être plus précis sur ce que vous avez vraiment besoin. Pouvons-nous générer le regexp programme? Deos il doit être réégien?


@gorn sûr, vous pouvez le construire de manière programmative (comme certaines des réponses déjà impliquées) et non, ce n'est pas vraiment être une regex (ce dont j'ai vraiment besoin, c'est simplement compter comment Beaucoup de personnages dans la botte de foin appartiennent à au moins un des substrings ) mais j'ai commencé à me demander comment faire avec une regex, ne pouvait pas et pensais que cela pourrait faire un bon Alors question.


Est-ce que vous réalisez que "appartient à au moins une sous-chaîne de au moins longueur N" est identique à "appartient à au moins une sous-chaîne de exactement longueur n"? C'est vraiment facile par programme de cette façon, mais je ne peux pas le faire avec une regex.


@Wolframh je l'ai déjà résolu d'une autre manière sans avec des regexes. Cette question, cependant, consiste à résoudre le problème en utilisant regexes. Mettez-vous d'une autre manière, cette question est purement académique.


4 Réponses :


1
votes

Y a-t-il un meilleur moyen de créer une regex qui correspondra à l'un des Substrings d'une chaîne donnée?

Non. Mais vous pouvez générer une telle expression facilement.


5 commentaires

VOTRE REGEX N (?: E (?: E (?: D (?: D (?: L (?: E?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)? / code>? On ne ressemble pas à ça.


Ce ne sera qu'un exemple de partie de l'expression complète qui en contiendrait plusieurs.


Ensuite, c'est encore moins élégant que ma solution, n'est-ce pas?


Et c'est ce que j'ai dit dans ma réponse.


+ Non. Ce n'est pas vraiment ce que le regex fait.



4
votes

comme Qtax suggéré, l'expression

n (e (e (d (d (l (e)?)?)?)?)?)?)? | e (E (d (d (l (e)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)? l (e)?)?)? | D (l (e)?)? | L (e)? | E

serait la voie à suivre si vous vouliez écrire une expression régulière explicite ( Egrep Syntaxe, remplacez éventuellement (code> (...) par (?: ...) ). La raison pour laquelle cela vaut mieux que la solution initiale est que la version condensée nécessite uniquement un espace O (n ^ 2) par rapport à l'espace O (n ^ 3) dans la version d'origine, où n est la longueur de l'entrée. Essayez-le avec extraordinairement comme entrée pour voir la différence. Je suppose que la version condensée est également plus rapide avec de nombreux moteurs Regexp.

L'expression

nee (d (l (l (e)?)?)? | EED (L (E)?)? | EDL (E)? | DLE

recherchera des sous-chaînes de longueur 3 ou plus.

Comme indiqué par Vhallac, les expressions régulières générées sont un peu redondantes et peuvent être optimisées. Outre l'outil Emacs proposé, il existe un package perl Regexp :: Optimizer que j'ai espéré aiderait ici, mais un chèque rapide a échoué pour la première expression régulière.

Notez que de nombreux moteurs REGEXP effectuent des recherches non superposées par défaut. Vérifiez cela avec les exigences de votre problème.


5 commentaires

EMacs ' regexp-opt génère des expecteurs légèrement plus courtes: (dle? | E (dle? Ed (le?)? | [DE]) | LE | NE (E (D ?)?)?)? | [Deln]) et (DLE | E (DLE? ED (LE?)?) | NEE (?: Le?)?)?)? )


Est-ce que cela est fourni dans une bibliothèque afin qu'il puisse être utilisé chez des emacs extérieurs?


Oups. J'ai oublié de supprimer quelques ?: s sur la seconde: (dle | e (dle? | Ed (le?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)?)


La source est disponible, mais c'est dans ELISP. Donc, vous préférez probablement simplement appeler des emacs en mode batch pour générer ces chaînes. Vous pouvez également inversion d'ingénieur et de réimplément dans une autre langue.


Si vous voulez jeter un oeil: koders.com/ Lisp / ...



-2
votes

Peut-être que vous cherchez juste . * (. {1,6}). *


4 commentaires

PS Je ne vois pas pourquoi vous n'avez pas inclus les sous-chaînes dupliquées. Cela les incluront afin que vous devrez vous en occuper de manière programmative, par exemple en utilisant un ensemble de hachage.


Cela correspondra à n'importe quoi ... Je ne vois pas comment votre réponse est liée à ma question ...


Il correspondra à toutes les sous-chaînes d'une chaîne. Ou je ne te comprends pas correctement?


CAFXX a demandé une correspondance de toutes les sous-chaînes de aiguille dans un autre texte plus grand.



3
votes

J'ai trouvé l'élégant presque resolution , en fonction de la peine dont vous n'avez besoin que d'un non plus réégien. Par exemple, voici la réégyclette, qui trouve la sous-chaîne commune de la longueur 7: xxx

la chaîne correspondante est dans \ 1 . Les chaînes ne doivent pas contenir de caractère nulle utilisé comme séparateur.

Vous devez faire un cycle qui met en marche avec la longueur de l'aiguille et descend jusqu'au cathold et essaie de faire correspondre la réégyclette.


4 commentaires

Élégant! Que diriez-vous du temps d'exécution?


Très impressionnant. Une question, cependant: ne correspondrait-elle pas, disons, "EE ED" (ou dans des chaînes courtes consécutives générales dans votre foin)?


@vhallac: Désolé, je ne vois pas pourquoi cela ferait cela - alors \ 0 sert de séparateur. Ce ne devrait pas être dans aucune des chaînes.


Aha, j'ai mal compris votre solution. Pour une raison quelconque, je pensais que $ aiguille contiendrait toutes les sous-chaînes. Désolé. :)