C++でアルファベット順に並ぶ部分文字列の個数を求める方法
問題の概要
長さ n の文字列を考えます。この文字列には大文字のアルファベットのみが含まれており、その中から「各文字がアルファベット順(A→B→C…)に連続して並んでいる」部分文字列の個数を求めます。なお、部分文字列の最小サイズは 2 とします。
例えば、文字列が「REFJHLMNBV」の場合、条件を満たす部分文字列は「EF」と「MN」の 2 つとなります。
解決のための手順
この問題は、文字列を一度走査するだけで効率的に解くことができます。手順は以下の通りです。
- 隣り合う文字同士を比較し、str[i] + 1 が str[i + 1] と等しい(=文字コード上で1つずつ連続している)かどうかを確認します。
- 等しい場合は、結果カウントを 1 増やし、アルファベット順から外れる文字が現れるまでインデックスを読み進めて、連続した並びをひとまとまりとして処理します。
- 等しくない場合は、そのまま次の文字へ移動します。
この手法により、計算量は O(n) となり、長い文字列でも高速に処理できます。
サンプルコード
#include<iostream>
using namespace std;
int countSubstr(string main_str) {
int res = 0;
int n = main_str.size();
for (int i = 0; i < n - 1; i++) {
if (main_str[i] + 1 == main_str[i + 1]) {
res++;
while (main_str[i] + 1 == main_str[i + 1]) {
i++;
}
}
}
return res;
}
int main() {
string str = "REFJHLMNBV";
cout << "Number of substrings: " << countSubstr(str);
}実行結果
Number of substrings: 2
コードのポイント
外側の for ループで文字列全体を走査し、連続するアルファベットを見つけた時点でカウントを 1 増やした後、内側の while ループでその連続部分を一気にスキップしています。これにより、同じ並びを二重に数えてしまうことを防いでいます。上記の例では「REFJHLMNBV」の中に「EF」と「MN」の 2 箇所が該当するため、出力は 2 になります。
-
C++で一方の文字列の部分文字列がもう一方の文字列にいくつ含まれるかを調べる方法
この記事では、2つの文字列が与えられたとき、1つ目の文字列の部分文字列のうち、2つ目の文字列内に存在するものがいくつあるかを求める方法を解説します。なお、同じ部分文字列が複数回出現する場合は、その回数もカウント対象となります。具体例入力 : string1 = fogl string2 = google 出力 : 6 説明 : string2 内に存在する string1 の部分文字列は [ o, g, l, og, gl, ogl ] の6個です。 入力 : string1 = ajva string2 = java 出力 : 5 説明 : str
-
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 の部分文字列の個数を順に加算していく必要があります。部分文