Afficher le nombre de fois que se repete une sous-chaine dans une chaine

Le problème exposé dans ce sujet a été résolu.

Programme permettant de compter le nombre de fois que se répète un sous-ensemble dans un ensemble.

Voici le code :

#include <iostream>
#include <string>
#include <algorithm>

int main ()
{
    std::string const sentence { "La beaute de son visage se refletait sur son monde a elle,\net son Seigneur lui fait dons d'une beaute sans egale que nulle\nne peut s'empecher de la jalouser farouchement. Cette beaute qui fut\na l'origine de la creation divine." };
    std::string const subset { "beau" };

    long int distance { std::distance(std::begin(subset), std::end(subset)) };
    int count_subset { 0 };

    auto it_begin_sentence { std::begin(sentence) };
    auto iterator { std::search(it_begin_sentence, std::end(sentence), std::begin(subset), std::end(subset)) };

    while (iterator != std::end(sentence))
    {
        ++count_subset;
        iterator += distance;
        std::cout << *iterator << '\n'; // pour voire l'element sur lequel pointe iterator a chaque tour de boucle
        it_begin_sentence = iterator;
        iterator = std::search(it_begin_sentence, std::end(sentence), std::begin(subset), std::end(subset));
    }

    std::cout << count_subset << '\n';
    return 0;
} 
+0 -0

Bonjour,

Quel est le problème ?
En l’état, ton message s’apparente à du spam.

+0 -0

Mon intention c’était d’avoir des suggestions ou bien savoir s’il existe une fonction ou algorithme de la bibliothèque qui fait la même chose, et autre chose qui m’échappe car j’ai l’impression que ce que je fais est correcte ainsi il se peut que des mauvaises habitudes m’accompagnent.

J’espère que vous avez compris la ou je veux en venir… Je n’avais pas l’intention de faire du spam, je masque tout de même si aucune remarque n’est faite. Merci

En ce qui concerne les erreurs (oui c’est tjr un se devant le verbe : merci), j’en prends note et je l’ai corrige…

+0 -0

La manière dont tu codes est currieuse mais ça marche.

Je ne comprend pas pourquoi tu fais ça:

        iterator += distance;

Supposons que l’on cherche lala dans lalala ou teddyt dans T'as vu teddyteddyt ?
On ne le trouve qu’une seule fois.

Selon moi, tu ne dois avancé que de 1.

        iterator += 1;

Appart un autre petit point, tout me semble OK dans ton programme. ^^

L’autre petit point étant :

    std::cout << count_subset << '\n';

On utilise plutôt std::endl.

    std::cout << count_subset << std::endl;
+1 -0

Petit point important: tu parles d’ensembles, mais tu veux probablement dire séquence. D’un point de vue mathématique (et c’est aussi le cas en informatique), un ensemble ne peut pas contenir deux fois le même élément. Cela veut dire que soit l’ensemble que tu cherches est contenu (une fois) dans l’ensemble dans lequel tu cherches, soit il ne l’est pas.

Tu n’as pas non plus bien défini ce qui est sensé se passer lorsque la séquence que tu cherches peut se trouver plusieurs fois en se chevauchant (comme dans les exemples présentés par Ache). Si tu comptes tous les chevauchements (e.g. aa se trouves deux fois dans aaa), il serait plus simple de faire une simple boucle for qui parcours toutes les positions possible et regarde à chaque position si la sous-séquence qui commence à cette position commence par la séquence que tu cherches.

Au passage, il est aussi possible de faire ce genre de traitement de manière plus efficace en utilisant l’algorithme de Boyer-Moore.

Je ne comprend pas pourquoi tu fais ça:

        iterator += distance;

ache

Au debut je comptais sauter la sous-chaine rechercher mais je me rends compte mtn que c’était maladroite de ma part. De plus que si la sous-chaine rechercher se trouve a la fin de la sequence (texte sur lequel la recherche est effectuee), iterator pointe sur un espace virtuel apres iterator += distance; et std::search effectue son traitement dans cet espace. Ce qui n’est pas logique du tout et peut provoquer un comportement indetermine dans mon programme. Bref grace a vous, j’ai compris ceci en faisant un petit retour en arriere.

Pas pris en compte le chevauchement de la sous-sequence. OUI iterator += 1; c’est bien plus mieux.

Ravi de prendre connaissance de l’algorithme de Boyer Moore et pour la définition d’un ensemble (j’en prends note). Bref merci a vous 2.

+0 -0

J’avais lu quelques part que '\n' est plus optimise que std::endl

En ce qui concerne l’utilisation de la boucle for, j’ai reecrit le code comme ci-dessous mais il y a plus de ligne qu’avant, donc je crois que j’ai mal choisit les 3 parametres de for :

#include <iostream>
#include <string>
#include <algorithm>

int main ()
{
    std::string const string { "Elle est belle." };
    std::string const substring { "beau" };

    bool no_enter_loop { true };

    auto it_begin_string { std::begin(string) };
    auto iterator { std::search(it_begin_string, std::end(string), std::begin(substring), std::end(substring)) };

    for (int count_substring { 1 }; iterator != std::end(string); ++count_substring)
    {
        no_enter_loop = false; // Si je rentre dans la boucle
        iterator += 1;
        std::cout << *iterator << std::endl; // pour voir l'element sur lequel iterator pointe a chaque tour de boucle
        it_begin_string = iterator;
        iterator = std::search(it_begin_string, std::end(string), std::begin(substring), std::end(substring));

        if (iterator == std::end(string)) // juste avant la sortie de la boucle
        {
            std::cout << substring << " Se repete " << count_substring << " fois." << std::endl;
        }
    }

    if (no_enter_loop) // si je ne rentre pas dans la boucle
    {
        std::cout << substring << " Se repete " << 0 << " fois." << std::endl;
    }
    return 0;
}
+0 -0

Très concrètement, ça n’a pas d’importance. std::endl est plus claire que "\n".
Même si "\n" avait un avantage, il n’en reste pas moins clair sur ce qui est affiché.

Disons que dans tous les cas, l’affichage c’est lent. Alors on est pas à une condition ou un appel à de fonction près.

"\n" n’affiche pas vraiment "\n". Ça affiche l’équivalent d’un retour à la ligne sur le système (quand le flux est en mode fichier). std::endl fait la même chose, mais quand on le lit c’est claire.

+1 -0

Il me semble que '\n' et std::endl ne sont pas tout à fait pareils, même sous linux.

Sauf erreur, std::endl effectue un saut de ligne puis appelle flush. Ce qui est en effet plus lent, mais on a au moins la certitude que le résultat sera bien affiché, même si le programme plante juste après.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte