C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で文字Xで始まり文字Yで終わる部分文字列の個数を数える方法

文字列 str が与えられたとき、「先頭の文字が X と一致し、末尾の文字が Y と一致する」部分文字列がいくつあるかを数えるのが本記事の目的です。たとえば、入力が "artact"、X='a'、Y='t' の場合、条件を満たす部分文字列は "art"、"act"、"artact" の 3 つとなるため、答えは 3 になります。

具体例で理解する

例 1

入力 − str="abcccdef"、X='a'、Y='c'

出力 − 条件を満たす部分文字列の数: 3

説明 − 該当する部分文字列は次のとおりです。

"abc"、"abcc"、"abccc"。合計 3 個。

例 2

入力 − str="tempest"、X='t'、Y='t'

出力 − 条件を満たす部分文字列の数: 3

説明 − 該当する部分文字列は次のとおりです。

"t"(先頭)、"tempest"、"t"(末尾)。合計 3 個。

X と Y が同じ文字の場合でも、先頭の "t" と末尾の "t" はそれぞれ独立した部分文字列としてカウントされる点に注意してください。

アルゴリズムの考え方

文字列を先頭から順に走査し、文字 X を見つけるたびにその出現回数を記録します。そして文字 Y に出会ったタイミングで、それまでに数えた X の個数を答えに加算します。この方法なら、すべての部分文字列を実際に生成することなく、線形時間 O(n) で答えを求められます。

  • 文字列 str を受け取り、長さを str.size() で取得します。
  • 関数 X_Y(string str, int length, char X, char Y) は、文字列 str と文字 X・Y を引数に取り、X で始まり Y で終わる部分文字列の個数を返します。
  • 結果を格納する変数 count を 0 で初期化します。
  • x_total は、これまでに走査した範囲に含まれる文字 X の個数を表します(初期値 0)。
  • for ループで i=0 から i<length まで文字列を走査します。
  • str[i]==X のとき、x_total をインクリメントして X の出現数を更新します。
  • str[i]==Y のとき、count に x_total を加算します。まだ X が現れていなければ x_total は 0 なので加算しても影響はなく、X が存在していれば、現在の Y は「その X から始まる部分文字列」の末尾文字となります。
  • 最後に count を結果として返します。

C++ 実装例

#include <bits/stdc++.h>
using namespace std;
int X_Y(string str, int length, char X, char Y){
    int count = 0;
    int x_total = 0;
    for (int i = 0; i < length; i++){
        if(str[i] == X){
            x_total++;
        }
        if (str[i] == Y){
            count = count + x_total;
        }
    }
    return count;
}
int main(){
    string str = "defaabbcchhkl";
    int length = str.size();
    char X = 'd';
    char Y = 'a';
    cout<<"Count of substrings that starts with character X and ends with character Y are: "<<X_Y(str, length, X, Y);
    return 0;
}

実行結果

上記のコードを実行すると、次のような出力が得られます。

Count of substrings that starts with character X and ends with character Y are: 2

この例では、"d" で始まり "a" で終わる部分文字列は "defa" と "defaa" の 2 つであるため、正しく 2 が出力されます。文字列を一度だけ走査すればよいため、計算量は O(n) と非常に効率的です。

  1. C++で0と1の個数が等しいバイナリ部分文字列を数える方法

    問題概要文字列 s が与えられたとき、「0 の個数と 1 の個数が等しく、かつすべての 0 とすべての 1 がそれぞれ連続してまとまっている」ような部分文字列の総数を求めます。同じ内容の部分文字列が複数回現れる場合は、出現した回数だけカウントします。例えば、入力が 11001100 の場合、条件を満たす部分文字列は 1100、10、0011、01、1100、10 の 6 つとなるため、出力は 6 になります。解法の考え方この問題は、文字列を一度走査するだけで O(n) の計算量で解くことができます。ポイントは「現在の文字が連続している回数」と「直前まで別の文字が連続していた回数」を比較するとい

  2. 【C++】入力(a, b)から「a」で始まり「a」で終わる文字列を判定するDFAを構築するプログラム

    文字「a」と「b」から構成される文字列が与えられたとき、その文字列が「a」で始まり、かつ「a」で終わっているかどうかをDFA(決定性有限オートマトン)を用いて判定する方法を解説します。 DFA(決定性有限オートマトン)とは? 理論計算機科学の一分野である計算理論において、決定性有限オートマトン(DFA:Deterministic Finite Automata)とは、記号の列を受け入れるか拒否するかを判定する有限状態機械です。「決定的(Deterministic)」とは、現在の状態と入力記号が決まれば、遷移先の状態が必ず一意に定まることを意味します。 本記事では、入力 (a, b) から