Pythonで文字列をK回以内の移動で別の文字列へ変換できるか判定するプログラム
2つの文字列 s と t が与えられたとき、s を k 回以内の移動で t に変換できるかどうかを判定します。i 回目の移動では、次のいずれかの操作を行えます。
s内の任意のインデックスj(1始まり)を選択します。ただし1 <= j <= len(s)であり、jは過去の移動で一度も選択されていない必要があります。そのうえで、その位置の文字をi回シフトします。- 何もせず、そのままにしておきます。
ここで「シフトする」とは、その文字をアルファベット順で次の文字に置き換えることを意味します('z' の場合は 'a' へ折り返します)。したがって「文字を i 回シフトする」とは、この操作を i 回繰り返し適用することです。
たとえば、入力が s = "poput"、t = "vwput"、k = 9 の場合、出力は True になります。これは、i = 6 の移動で 'p' を 'v' に、i = 8 の移動で 'o' を 'w' にそれぞれ変換できるためです。
解法のアプローチ
この問題は、次の手順で解くことができます。
sとtの長さが一致しない場合は、Falseを返します。countを、0〜25 の各iについてmin(1, k - i + 1) + (k - i) // 26の値を持つ配列として初期化します。これは「ちょうど i 回のシフトを実現できる移動の残り回数」を表します。sとtの対応する文字c1、c2を順に調べます。c1とc2が異なる場合:diff := (ord(c2) - ord(c1) + 26) % 26を計算します。count[diff] <= 0ならばFalseを返します。count[diff]を 1 減らします。
- すべての文字を確認できたら
Trueを返します。
考え方のポイント
ある文字をちょうど diff 回シフトして一致させるには、「移動番号 i を 26 で割った余りが diff に等しい」ような i を使う必要があります。候補となるのは i = diff, diff+26, diff+52, … であり、k 回以内に含まれる個数が min(1, k - diff + 1) + (k - diff) // 26 で求まります。同じ diff が必要な文字同士でこの枠を共有するため、該当する文字のペアごとに 1 つずつ消費していき、足りなくなった時点で変換不可能と判断します。
それでは、実際の実装を見てみましょう。
サンプルコード(Python)
def solve(s, t, k): if len(s) != len(t): return False count = [min(1, k - i + 1) + (k - i)//26 for i in range(26)] for c1, c2 in zip(s, t): if (c1 != c2): diff = (ord(c2) - ord(c1) + 26) % 26 if count[diff] <= 0: return False count[diff] -= 1 return True s = "poput" t = "vwput" k = 9 print(solve(s, t, k))
入力
"poput","vwput",9
出力
True
計算量
時間計算量は O(n)(n は文字列の長さ)、追加で必要な空間計算量は O(1)(サイズ 26 の固定配列のみ)です。文字列の長さに比例して処理できるため、大きな入力にも効率的に対応できます。
-
指定された文字列がキーワードであるかどうかを確認するPythonプログラム
この記事では、指定された文字列がPythonのキーワード(予約語)であるかどうかを判定する方法について解説します。問題の概要与えられた文字列が、Pythonにおけるキーワードであるかどうかを確認する必要があります。キーワードとは、言語によって特別な用途のために予約されている単語であり、変数名や関数名などの識別子として使用することはできません。例えば「if」「for」「while」「def」などはすべてキーワードです。これらの名前を変数に使おうとすると、構文エラーが発生します。解決策:keywordモジュールの活用Pythonには標準ライブラリとしてkeywordモジュールが用意されており、これ
-
Pythonで文字列が回文かどうかを判定する方法
Pythonで回文判定を行う方法文字列が回文(前から読んでも後ろから読んでも同じになる文字列)であるかどうかを確認するには、Pythonの標準ライブラリに含まれる reversed() 関数を利用するのが便利です。この関数は逆順のイテレータオブジェクトを返し、それを list() でリストに変換することができます。手順1:reversed()で文字列を逆順にするまず、対象となる文字列を reversed() 関数に渡し、結果をリストとして取得します。>>> str1=malayalam >>> l1=list(reversed(str1)) >>