【C++】文字列内の「1(0+)1」パターンをすべて検出する方法
文字列の中に「1(0+)1」という形式のパターンが含まれていると仮定します。ここで「(0+)」は、1個以上の「0」が連続して現れることを意味します。この記事では、文字列からこのパターンをすべて検出する方法を解説します。パターン同士が重なり合う場合もカウントの対象とします。なお、対象の文字列はバイナリ文字列であるとは限らず、数字と小文字の英字のみで構成された文字列を扱います。
例として、文字列が「1101001」の場合を考えてみましょう。この場合、「101」と「1001」の2つのパターンが見つかります。
解決のためのアプローチ
この問題は、以下の手順に従って解くことができます。
文字列内のすべての文字cを先頭から順に走査します。
現在の文字が「0」で、直前の文字が「1」だった場合は、「0」が続く限り読み進めます。
「0」の連続が終わった時点で、その次の文字が「1」かどうかを確認します。「1」であればパターンが成立したものとしてカウントします。
これらの手順を文字列の末尾に到達するまで繰り返します。
C++による実装例
#include<iostream>
using namespace std;
int countBinPattern(string main_str) {
char last_char = main_str[0];
int i = 1, counter = 0;
while (i < main_str.size()) {
if (main_str[i] == '0' && last_char == '1') {
while (main_str[i] == '0')
i++;
if (main_str[i] == '1')
counter++;
}
last_char = main_str[i];
i++;
}
return counter;
}
int main() {
string str = "10010110000101";
cout << "Number of substrings of pattern 1(0+)1 is: " << countBinPattern(str);
}
実行結果
Number of substrings of pattern 1(0+)1 is: 4
コードの解説
この実装では、変数last_charで直前の文字を記憶しながら文字列を1文字ずつ走査します。現在の文字が「0」で直前の文字が「1」のとき、内部ループによって「0」の連続を一気にスキップし、連続が終わった位置の文字が「1」であればカウンタをインクリメントします。この仕組みにより、互いに重なり合うパターンも漏れなく数え上げることができます。
入力文字列「10010110000101」の場合、「1001」「101」「100001」「101」の4つのパターンが検出され、実行結果は4となります。
-
C++で文字列の部分文字列の総数を求める方法を解説
この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文
-
C++で完全二分木の全ノードの合計を効率的に求める方法
問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から