C++で文字列が長さKのすべてのバイナリコードを含むかどうかを判定する方法
二進文字列 s と整数 k が与えられたとき、長さ k のすべてのバイナリコード(合計 2^k 個)が s の部分文字列として含まれているかどうかを判定します。すべて含まれていれば true を、1つでも欠けていれば false を返します。
問題の例
たとえば、入力が S = "00110110"、k = 2 の場合、出力は true になります。長さ 2 のバイナリコードは「00」「01」「10」「11」の 4 種類あり、それぞれインデックス 0、1、3、2 の位置に存在するためです。
解法のアプローチ
この問題は、スライディングウィンドウの考え方とハッシュセットを組み合わせることで効率的に解くことができます。手順は以下の通りです。
- 重複しない部分文字列を記録するためのセット
vを定義します。 - 一時的な文字列
tempを空文字列で初期化します。 - 必要なコードの総数
req = 2^kを計算します。 i = 0からsの末尾まで以下を繰り返します。tempの末尾にs[i]を追加します。i >= kのとき、tempの先頭の 1 文字を削除し、ウィンドウの長さをkに保ちます。i >= k - 1のとき、長さkの部分文字列tempをセットvに挿入します。- セット
vのサイズがreqに達した時点で、すべてのコードが見つかったことになるのでtrueを返します。
- ループが終了しても条件を満たさなければ、
falseを返します。
この方法では、必要な種類数に達した時点で早期に処理を打ち切れるため、無駄な走査を避けられます。時間計算量は各ステップで長さ k の文字列操作が発生するため O(n・k)、空間計算量は O(2^k・k) となります。なお、部分文字列をビット値(整数)に変換して管理すれば、計算量を O(n) まで抑えることも可能です。
実装例
理解を深めるために、以下の C++ 実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;
class Solution {
public:
lli fastPow(lli b, lli p){
lli ret = 1;
while (p) {
if (p & 1) {
ret *= b;
}
b *= b;
p >>= 1;
}
return ret;
}
bool hasAllCodes(string s, int k) {
unordered_set<string> v;
string temp = "";
lli req = fastPow(2, k);
for (lli i = 0; i < s.size(); i++) {
temp += s[i];
if (i >= k) {
temp.erase(0, 1);
}
if (i >= k - 1) {
v.insert(temp);
}
if ((lli)v.size() == req)
return true;
}
return false;
}
};
main(){
Solution ob;
cout << (ob.hasAllCodes("00110110",2));
}
入力
"00110110",2
出力
1
出力が 1(true)となり、文字列「00110110」が長さ 2 のすべてのバイナリコードを含んでいることが確認できました。
-
【C++】二分木にサイズ2以上の重複する部分木が存在するかを判定する方法
問題の概要 二分木が与えられたとき、その木の中にサイズ2以上の同一の部分木(重複部分木)が存在するかどうかを判定するのが本記事のテーマです。例として、次のような二分木を考えてみます。 この木には、サイズ2の同一の部分木が2つ含まれています。このように、同じ構造・同じノード値を持つ部分木が複数存在するかどうかを効率よくチェックする必要があります。 アプローチ:シリアライズとハッシュの活用 この問題は、部分木のシリアライズ(文字列化)とハッシュテーブルを組み合わせることで効率的に解くことができます。基本的なアイデアは以下の通りです。 各ノードから再帰的に部分木を文字列としてシリアライズし、ハ
-
【Python】文字列がすべてユニークな文字で構成されているか判定する方法
本記事では、与えられた文字列に含まれる文字がすべて一意(ユニーク)であるかどうかを判定するPythonプログラムについて、その解法とアプローチをわかりやすく解説します。 問題の概要 文字列が入力として与えられたとき、その文字列に含まれるすべての文字が重複なく一意であるかどうかを判定します。たとえば「abcde」はすべて異なる文字で構成されているためTrue、「tutorialspoint」のように同じ文字が複数回出現する場合はFalseとなります。 アプローチ この問題は、以下のような手順で効率的に解くことができます。 ブール値の配列を用意する: 各インデックス i が「アルファベット(AS