{ }codelper
文字列の検索P0030

重なりも含めて出現回数を数える

一行目に文章 text、二行目に探す語 pattern が与えられる。
text の中に pattern が何回現れるか出力せよ。
現れた位置どうしが重なっても別々に数える。
たとえば "aaaa" には "aa" が 0、1、2 番目の位置から始まって全部で 3 回現れる。
pattern が text より長ければ 0 である。

入力
text は英小文字、長さ 1〜5,000。
pattern は英小文字、長さ 1〜10
出力
現れた回数
例 1 · stdin
aaaa
aa
stdout
3
例 2 · stdin
abababa
aba
stdout
3
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

「何回現れるか」を一度で数える関数は重ならないように数えます:Python text.count("aa") は "aaaa" で 2 です。
重なりも数えるには、見つけた位置のすぐ次(+1)から探し直します:Python text.find(p, i + 1)、JS・TS・Java indexOf(p, i + 1)、C# IndexOf(p, i + 1, StringComparison.Ordinal)、C++ find(p, i + 1)、C strstr(q + 1, p)(見つけた所のポインタを返します)。
Craykon の 位置検索 は開始位置を受け取らないので、位置ごとに text.切り出す(i, m) == pattern で比べます。
落とし穴:見つけた後にパターンの長さ(+m)だけ飛ばすと、組み込みの count と同じく重なりを見落とします。

Pythonmain.py · 8 行
text = input()pattern = input()count = 0i = text.find(pattern)while i != -1:    count += 1    i = text.find(pattern, i + 1)print(count)
JavaScriptmain.js · 4 行
const [text, pattern] = require("fs").readFileSync(0, "utf8").split("\n").map((s) => s.trim());let count = 0;for (let i = text.indexOf(pattern); i !== -1; i = text.indexOf(pattern, i + 1)) count++;console.log(count);
TypeScriptmain.ts · 5 行
import { readFileSync } from "node:fs";const [text, pattern]: string[] = readFileSync(0, "utf8").split("\n").map((s) => s.trim());let count = 0;for (let i = text.indexOf(pattern); i !== -1; i = text.indexOf(pattern, i + 1)) count++;console.log(count);
JavaMain.java · 13 行
import java.io.BufferedReader;import java.io.InputStreamReader; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        String text = br.readLine().trim();        String pattern = br.readLine().trim();        int count = 0;        for (int i = text.indexOf(pattern); i != -1; i = text.indexOf(pattern, i + 1)) count++;        System.out.println(count);    }}
C#Main.cs · 15 行
using System; class Program{    static void Main()    {        string text = Console.ReadLine().Trim();        string pattern = Console.ReadLine().Trim();        int count = 0;        for (int i = text.IndexOf(pattern, StringComparison.Ordinal); i != -1;             i = text.IndexOf(pattern, i + 1, StringComparison.Ordinal))            count++;        Console.WriteLine(count);    }}
C++main.cpp · 10 行
#include <iostream>#include <string> int main() {    std::string text, pattern;    std::cin >> text >> pattern;    int count = 0;    for (size_t i = text.find(pattern); i != std::string::npos; i = text.find(pattern, i + 1)) count++;    std::cout << count << "\n";}
Cmain.c · 13 行
#include <stdio.h>#include <string.h> static char text[5005]; int main(void) {    char pattern[16];    if (scanf("%5000s %10s", text, pattern) != 2) return 0;    int count = 0;    for (char* p = strstr(text, pattern); p != NULL; p = strstr(p + 1, pattern)) count++;    printf("%d\n", count);    return 0;}
Craykonmain.cray · 12 行
text = コンソール.行読み().空白除去();pattern = コンソール.行読み().空白除去();m = pattern.長さ;count = 0;繰り返す (i = 0; i + m <= text.長さ; i++){    もし (text.切り出す(i, m) == pattern)    {        count++;    }}コンソール.書く(count);