Pythonで「A」と「B」の移動制約のもと、ある文字列を別の文字列へ変換できるか判定する方法
問題の概要
「A」「B」「#」の3種類の文字だけで構成された2つの文字列 s と t が与えられます。ここで、次のルールに従う操作によって s を t へ変換できるかどうかを判定するのが、この記事のテーマです。
- 「A」は左方向にしか移動できない
- 「B」は右方向にしか移動できない
- 「A」と「B」は互いに交差(追い越し)できない
例として、s = '##AB##B'、t = 'A###B#B' という入力を考えてみましょう。この場合の出力は True になります。s 内の A は左端の位置へスムーズに移動でき、中央の B も1ステップ右へ動けるためです。
解法の考え方
この問題は、貪欲法(グリーディ法)によるマッチングで解くことができます。手順は以下の通りです。
- s と t をそれぞれ文字のリストに変換します。
- 両者の長さが異なる場合は False を返します。
- s と t に含まれる「A」の個数、または「B」の個数が一致しない場合も False を返します。
- s の各位置 i について、s[i] が「#」でない場合は、t を先頭から走査し、最初に一致する文字を探します。
- t[j] が s[i] と異なる文字で、かつ「#」でもない場合は False を返します。
- t[j] が s[i] と一致したら、その位置を「#」で埋めて使用済みにします。
- s[i] が「A」なのに i < j の場合(A が右へ移動することになる)は False を返します。
- s[i] が「B」なのに i > j の場合(B が左へ移動することになる)は False を返します。
- マッチングが完了したら内側のループを抜けます。
- すべての文字が条件を満たしていれば True を返します。
重要なポイントは、「A」の移動後の位置 j は元の位置 i 以下(j ≤ i)である必要があり、「B」の移動後の位置 j は元の位置 i 以上(j ≥ i)である必要がある点です。この条件を満たさないペアが1つでも存在すれば、変換は不可能と判断できます。
Pythonでの実装例
それでは、上記のアルゴリズムをPythonで実装してみましょう。
def solve(s, t):
s = list(s)
t = list(t)
if len(s) != len(t):
return False
if s.count('A') != t.count('A') or s.count('B') != t.count('B'):
return False
for i in range(len(s)):
if s[i] != '#':
for j in range(len(t)):
if (t[j] != s[i]) and t[j] != '#':
return False
if t[j] == s[i]:
t[j] = '#'
if s[i] == 'A' and i < j:
return False
if s[i] == 'B' and i > j:
return False
break
return True
s = '##AB##B'
t = 'A###B#B'
print(solve(s, t))
入力
'##AB##B', 'A###B#B'
出力
True
計算量の目安
このアルゴリズムの時間計算量は O(n²) です。外側のループで s の各文字を確認し、内側のループで t を走査するためです。空間計算量は O(n) となり、文字列をリストに変換する分だけメモリを使用します。
より高速に処理したい場合は、あらかじめ t 内の「A」と「B」の位置インデックスをそれぞれキューに記録しておき、s を走査しながら対応する位置と順番に比較する方法(O(n))も有効です。
-
Pythonで文字列化されたリストをリスト型に変換する3つの方法
Pythonはさまざまなデータ型を扱えるため、開発中に「リストが文字列として表現されている」場面に遭遇することがあります。例えば、APIのレスポンスやファイルから読み込んだデータが、[Mon, 2, Tue, 5] のような文字列になっているケースです。この記事では、そのような文字列を実際のリストに変換する3つの方法を、サンプルコードとともにわかりやすく解説します。 1. strip() と split() を組み合わせる方法 まず strip() メソッドを使って文字列の前後にある角括弧 [ ] を取り除き、その後に split() 関数を適用します。split() の引数にカンマを指定する
-
Pythonで文字列を別の文字列に追加(連結)する2つの方法
Pythonにおいて「文字列を追加する」というのは、複数の文字列をつなぎ合わせて新しい文字列を作ること(連結)を意味します。テキスト解析など、さまざまな場面で活用される基本的な操作です。この記事では、ある文字列を別の文字列に追加するための代表的な2つの方法を、サンプルコードと実行結果とともに解説します。方法1:+= 演算子を使う+ 演算子は、数値に対して使う場合と同じように文字列にも使用できます。ただし、文字列の場合は数値の加算ではなく連結が行われる点が異なります。コード例s1 = What a beautiful s2 = flower print(与えられた文字列 s1 :, s1)