C++ STLを使った長さ2の異なる連続部分文字列の個数を数える方法
はじめに
本記事では、C++のSTL(標準テンプレートライブラリ)を活用して、与えられた文字列の中に現れる長さ2の異なる連続部分文字列を抽出し、それぞれの出現回数を数えて表示するプログラムについて解説します。
問題の概要
入力として1つの文字列が与えられます。私たちのタスクは、文字列から隣接する2文字ずつを取り出し、重複を除いたすべての部分文字列(長さ2)とその出現回数を求めて出力することです。
例えば、文字列 "abcacdcacabacaassddssklac" の場合、「ab」「bc」「ca」などのペアが登場します。同じペアが何度現れても1種類として扱い、出現回数を記録するのがポイントです。
実装のアプローチ
この問題は、std::map と std::pair を組み合わせることで簡潔に解決できます。
- キー: 隣接する2文字
(str[i], str[i+1])をpair<char, char>として表現 - 値: そのペアが出現した回数(int)
map は自動的にキーでソートされるため、結果は昇順に整列されて出力されます。
サンプルコード
#include<bits/stdc++.h>
using namespace std;
void calc_distinct(string str){
// 2文字のペアごとの出現回数を記録するマップ
map<pair<char,char>, int> dPairs;
for (int i=0; i<str.size()-1; i++)
dPairs[make_pair(str[i], str[i+1])]++;
cout << "Distinct sub-strings with counts:\n";
for (auto it=dPairs.begin(); it!=dPairs.end(); it++)
cout << it->first.first << it->first.second << "-" << it->second << " ";
}
int main(){
string str = "abcacdcacabacaassddssklac";
calc_distinct(str);
return 0;
}実行結果
Distinct sub-strings with counts: aa-1 ab-2 ac-4 as-1 ba-1 bc-1 ca-4 cd-1 dc-1 dd-1 ds-1 kl-1 la-1 sd-1 sk-1 ss-2
コードの解説
- マップの準備:
dPairsは、2文字のペアをキー、出現回数を値として保持します。 - 走査とカウント: ループで文字列を先頭から末尾まで走査し、各位置で現在の文字と次の文字をペアにして、マップ内の該当キーのカウントをインクリメントします。
- 結果の出力: イテレータでマップを巡回し、「2文字のペア - 出現回数」の形式で出力します。
mapの特性により、キーは昇順に並んでいます。
まとめ
C++ STLの map を使えば、長さ2の異なる連続部分文字列の抽出と出現回数の集計を、わずか十数行のコードで実現できます。文字列の長さをNとすると計算量は O(N log N) 程度に収まり、効率的な処理が可能です。この手法は、n-gram解析など他の文字列処理タスクにも応用できるため、ぜひ覚えておきましょう。
-
C++を使ってランダムな英数字文字列を生成する方法
この記事では、C++を使ってランダムな英数字文字列を生成する方法を解説します。対象となる文字は、小文字(a〜z)、大文字(A〜Z)、そして数字(0〜9)です。プログラムはこれらの文字の中からランダムに1文字ずつ選び、指定された長さのランダムな文字列を作成します。入力:生成する文字列の長さを指定出力:指定した長さのランダム文字列 例:「XSme6VAsvJ」アルゴリズムステップ1:大文字・小文字・数字をすべて格納する配列を定義するステップ2:ユーザーから文字列の長さ n を受け取るステップ3:n 回ランダムに文字を選択し、長さ n の文字列を生成するステップ4:終了サンプルコード以下のコードでは
-
C++で文字列に部分文字列が含まれているか確認する方法|find()関数の使い方を解説
ここでは、C++の標準文字列ライブラリ(std::string)を使って、メイン文字列の中に特定の部分文字列(サブストリング)が含まれているかどうかを確認する方法を解説します。検索には find() 関数を使用します。find() は、部分文字列が最初に出現する位置を返すため、この関数を繰り返し呼び出せば、メイン文字列内のすべての出現箇所を取得することができます。部分文字列が見つかった場合、find() はその位置(インデックス)を返します。一方、見つからなかった場合は特別な定数 string::npos を返します。したがって、「部分文字列がメイン文字列に存在するかどうか」を判定したい場合は