Médio C++

Contando ocorrências de uma substring

Enunciado

Leia uma linha de texto e uma palavra, e conte quantas vezes a palavra aparece no texto (sobreposições contam).

Requisitos

  • Usar find em um laço para localizar todas as ocorrências.
  • Considerar ocorrências sobrepostas, avançando a busca em 1 caractere.
  • Imprimir apenas o número inteiro de ocorrências.

Código inicial

#include <iostream>
#include <string>

int main() {
    std::string texto, palavra;
    std::getline(std::cin, texto);
    std::getline(std::cin, palavra);
    // TODO: conte as ocorrências de palavra em texto
    return 0;
}

Saída esperada

3
Ver dica

Depois de encontrar, avance a posição de busca em 1 para permitir sobreposições.

Mostrar solução
#include <iostream>
#include <string>

int main() {
    std::string texto, palavra;
    std::getline(std::cin, texto);
    std::getline(std::cin, palavra);

    int contador = 0;
    std::size_t pos = 0;
    while ((pos = texto.find(palavra, pos)) != std::string::npos) {
        ++contador;          // encontrou uma ocorrência
        pos += 1;            // avança 1 para permitir sobreposição
    }

    std::cout << contador << '\n';
    return 0;
}

Passo a passo

  1. Lemos o texto e a palavra com getline, pois podem conter espaços.
  2. contador guarda quantas vezes encontramos.
  3. pos começa em 0 e é atualizada a cada busca.
  4. texto.find(palavra, pos) procura a partir de pos; se não achar, retorna npos e o laço termina.
  5. A cada acerto, incrementamos contador e somamos 1 a pos para não pular sobreposições.
  6. Por fim, imprimimos o total.

Por que funciona

O laço usa o retorno de find como condição. Avançar apenas 1 caractere permite detectar ocorrências que se sobrepõem, como "aa" em "aaa".

Erros comuns

  • Avançar pos += palavra.size(): perde sobreposições.
  • Não usar std::size_t para pos: risco de conversão e comparação incorreta com npos.
  • Chamar find sem segundo argumento dentro do laço: sempre encontra a primeira ocorrência e entra em loop infinito.

Outra forma de resolver

Usar std::string_view para evitar cópias e manter a mesma lógica:

std::string_view sv{texto};
size_t pos = 0;
while ((pos = sv.find(palavra, pos)) != std::string_view::npos) {
    ++contador;
    ++pos;
}

Saída esperada

3