復号化した文字列のk番目の文字を求める方法 – Pythonでの実装
問題の概要
エンコードされた文字列では、部分文字列の繰り返しが「部分文字列+出現回数」の形式で表現されます。たとえば、文字列が pq2rs2 で k=5 の場合、復号化後の文字列は pqpqrsrs となり、5番目の文字は r です。
ここで注意したいのは、出現回数が2桁以上になるケースも存在するという点です。たとえば a12b のような入力では、「a」が12回繰り返されることを正しく読み取れる必要があります。
具体例
入力として string = "pq4r2ts3"、k = 11 が与えられた場合を考えてみましょう。復号化後の文字列は pqpqpqpqrrtststs となるため、11番目の文字である t が出力されます。
解法のアプローチ
この問題は、次の手順で解くことができます。
- 復号化結果を格納する
encodedを空文字列で初期化します。 - 出現回数
occurrenceを 0、走査用のインデックスiを 0 とします。 iが文字列の長さに達するまで、以下を繰り返します。tempを空文字列、occurrenceを 0 にリセットします。str[i]がアルファベットである間、その文字をtempに追加しながらiを進めます。str[i]が数字である間、occurrence = occurrence * 10 + 数値として桁を組み立てながらiを進めます。これにより、2桁以上の出現回数にも対応できます。jを 1 からoccurrenceまでループして、encodedにtempを追加します。occurrenceが 0 の場合(回数指定がない場合)は、encodedにtempを1回だけ追加します。
- 最後に
encoded[k - 1]を返せば、答えが得られます。
Pythonでの実装例
それでは、実際のコードを見ていきましょう。
def find_kth_char(input_str, k):
encoded = ""
i = 0
while i < len(input_str):
temp = ""
occurrence = 0
# アルファベット部分を読み取る
while i < len(input_str) and input_str[i].isalpha():
temp += input_str[i]
i += 1
# 数字部分を読み取る(複数桁にも対応)
while i < len(input_str) and input_str[i].isdigit():
occurrence = occurrence * 10 + int(input_str[i])
i += 1
# 出現回数に応じて復号化文字列を構築
if occurrence == 0:
encoded += temp
else:
for _ in range(occurrence):
encoded += temp
return encoded[k - 1]
input_str = "pq4r2ts3"
k = 11
print(find_kth_char(input_str, k))
入力
"pq4r2ts3", 11
出力
t
計算量と補足
この手法の時間計算量は、復号化後の文字列の長さを N とすると O(N) です。一方で、出現回数が非常に大きい場合は、復号化後の文字列全体をメモリ上に展開するとメモリを大きく消費する可能性があります。そのようなケースでは、文字列を実際に展開せずに、各ブロックの累積文字数を数えながら k 番目の文字が属する位置を特定する方式が有効です。
-
Pythonで文字列内のn番目に出現する部分文字列の位置を見つける方法
Pythonでは、split()メソッドを活用することで、文字列内にn番目に出現する部分文字列の位置(インデックス)を簡単に求めることができます。基本的な考え方手順は以下の通りです。対象の部分文字列を区切り文字として、最大 n+1 回だけ文字列を分割します。分割後のリストの要素数が n+1 より大きければ、その部分文字列は少なくとも n 回以上出現していることになります。出現位置は、「元の文字列の長さ − 最後の分割部分の長さ − 部分文字列の長さ」というシンプルな式で計算できます。コード例def findnth(string, substring, n): parts = strin
-
【Python】文字列内の部分文字列が最後に出現するインデックスを取得する方法
Pythonでは、rfind()メソッドを使うことで、文字列の中に部分文字列が最後に出現する位置(インデックス)を簡単に調べることができます。 rfind()メソッドの基本 rfind()は、文字列の末尾から前方に向かって部分文字列を検索するメソッドです。動作は以下の通りです。 部分文字列が見つかった場合 → 最後に出現した位置のインデックスを返す 見つからなかった場合 → -1 を返す 使用例 >>> some of the some.rfind(some) 12 >>> some of the some.rfind(none) -1 >>