C++で文字列が「多様(ダイバース)」かどうかを判定する方法
問題の概要
小文字の英字からなる長さ n の文字列 S が与えられたとします。このとき、次の条件をすべて満たす文字列を「多様な文字列(diverse string)」と呼びます。
- アルファベットが連続して並んでいること
- それぞれの文字がちょうど1回だけ出現すること
- なお、「a」と「z」は隣接しているものとはみなさない
この記事では、与えられた文字列 S が多様な文字列であるかどうかを C++ で判定する方法を解説します。
例えば、入力が S = "fced" の場合、文字を並べ替えると c, d, e, f となり、アルファベットが連続しているため、出力は True(1)になります。
解き方の手順
この問題は、以下の手順で解くことができます。
- 文字列 S を昇順にソートする
- フラグ変数 flag を 1 で初期化する
- i を 1 から開始し、i が S のサイズ未満かつ flag が 0 でない間、次の処理を繰り返す
・S[i] − S[i − 1] が 1 ではない場合、flag を 0 に設定する - flag が 0 以外であれば true、そうでなければ false を返す
実装例
理解を深めるために、実際の C++ コードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
bool solve(string S){
sort(S.begin(), S.end());
int flag = 1;
for (int i = 1; i < S.size() && flag; i++)
if (S[i] - S[i - 1] != 1)
flag = 0;
return flag ? true : false;
}
int main(){
string S = "fced";
cout << solve(S) << endl;
}
入力
"fced"
出力
1
まとめ
このアルゴリズムのポイントは、まず文字列をソートすることです。多様な文字列であれば、ソート後は必ず「b, c, d…」のように隣接する文字同士の差が 1 になります。そのため、隣接する文字の差分を順番にチェックするだけで判定できます。
計算量は、ソート部分が O(n log n)、比較部分が O(n) となり、非常に効率的な手法です。文字列操作の基礎的な練習問題として、ぜひ参考にしてください。
-
【C++入門】バイナリ文字列の「1」の間に「0」が含まれているかを判定する方法
今回は少し面白い文字列処理の問題を取り上げます。与えられたバイナリ文字列(0と1のみで構成された文字列)について、「1」の並びの中に「0」が挟まっていないかどうかを判定します。「0」が含まれていなければその文字列は有効(valid)、含まれていれば無効(invalid)とみなします。問題の例次の3つの文字列を見てみましょう。A:10001111010B:00001111100C:01111101111この中で有効なのは B の「00001111100」だけです。B は先頭から最初の「1」まで、そして最後の「1」以降には「0」がありますが、連続する「1」のブロック内部には「0」が一切存在しないた
-
C++で文字列に部分文字列が含まれているか確認する方法|find()関数の使い方を解説
ここでは、C++の標準文字列ライブラリ(std::string)を使って、メイン文字列の中に特定の部分文字列(サブストリング)が含まれているかどうかを確認する方法を解説します。検索には find() 関数を使用します。find() は、部分文字列が最初に出現する位置を返すため、この関数を繰り返し呼び出せば、メイン文字列内のすべての出現箇所を取得することができます。部分文字列が見つかった場合、find() はその位置(インデックス)を返します。一方、見つからなかった場合は特別な定数 string::npos を返します。したがって、「部分文字列がメイン文字列に存在するかどうか」を判定したい場合は