復号化された文字列のk番目の文字を求める – C++実装(セット2)
概念
エンコードされた文字列では、部分文字列の繰り返しが「部分文字列+繰り返し回数」の形式で表されます。例えば、暗号化された文字列が「pq2rs2」で k=5 の場合、復号化された文字列は「pqpqrsrs」となり、5番目の文字は「r」であるため、出力は「r」になります。
なお、暗号化された部分文字列の繰り返し回数は2桁以上になることもあります。例えば「pq12r3」では、「pq」が12回繰り返されます。このとき、繰り返し回数の先頭に0が付くことはありません。
入力例
"p2q2r3", k = 6
出力
r
復号化された文字列は「ppqqrrr」です。
入力例
"pq4r2ts3", k = 11
出力
t
復号化された文字列は「pqpqpqpqrrtststs」です。
アルゴリズム(解法手順)
- 現在の部分文字列の長さを求めます。2つのポインタを使用し、1つを部分文字列の先頭に固定し、もう1つを数字が見つかるまで進めます。
- 2つ目のポインタをさらに進め、アルファベットが見つかるまで移動することで、部分文字列の繰り返し回数(頻度)を求めます。
- 頻度に元の部分文字列の長さを掛け合わせて、繰り返し後の部分文字列の長さを求めます。
- この長さが k より小さい場合、目的の文字は次の部分文字列に存在します。k からこの長さを引くことで、まだカバーすべき文字数を管理します。
- この長さが k 以上の場合、目的の文字は現在の部分文字列内に存在します。k は1始まりのインデックスであるため、1を引いた後、元の部分文字列の長さで剰余を取ります。こうして得られた位置、すなわち最初のポインタが指す部分文字列の先頭から k 番目の文字が答えとなります。
実装例(C++)
// 復号化された文字列からK番目の文字を求めるC++プログラム
#include <bits/stdc++.h>
using namespace std;
// エンコードされた文字列からK番目の文字を求める関数
char encodedChar(string str, int k) {
int a, b;
int m = str.length();
int len1; // 部分文字列の長さを格納
int num1; // 繰り返し後の部分文字列の長さを格納
int freq1; // 部分文字列の繰り返し回数を格納
a = 0;
while (a < m) {
b = a;
len1 = 0;
freq1 = 0;
// 数字が見つかるまで文字列を走査し、部分文字列の長さを求める
while (b < m && isalpha(str[b])) {
b++;
len1++;
}
// 直前の部分文字列の繰り返し回数を求める
while (b < m && isdigit(str[b])) {
freq1 = freq1 * 10 + (str[b] - '0');
b++;
}
// 繰り返し後の部分文字列の長さを求める
num1 = freq1 * len1;
// 繰り返し後の長さがkより小さい場合、目的の文字は
// 次の部分文字列に存在する。kから長さを引いて、
// 残りカバーすべき文字数を管理する
if (k > num1) {
k -= num1;
a = b;
}
// 繰り返し後の長さがk以上の場合、
// 目的の文字は現在の部分文字列内に存在する
else {
k--;
k %= len1;
return str[a + k];
}
}
// 文字列に繰り返しが含まれない場合の処理
// 例: str="abced"
return str[k - 1];
}
// ドライバーコード
int main() {
string str1 = "pqpqpqpqrrtststs";
int k1 = 11;
cout << encodedChar(str1, k1) << endl;
string str2 = "p2q2r3";
int k2 = 6;
cout << encodedChar(str2, k2) << endl;
return 0;
}出力
t r
計算量
このアルゴリズムは、エンコードされた文字列を一度だけ走査するため、時間計算量は O(n)(n はエンコードされた文字列の長さ)です。また、補助的な記憶領域は O(1) で済みます。実際に復号化後の文字列を構築しないため、展開後の文字列が非常に長くなる場合でも、効率的に目的の文字を求められる点が大きな利点です。
-
C#で文字列の最初の文字を取得するには?
C#で文字列の先頭の1文字を取得したい場合、Substring()メソッドを使うのが最もシンプルで一般的な方法です。対象となる文字列の例まず、次のような文字列があったとします。string str = Welcome to the Planet!;Substring()メソッドで最初の文字を取り出す最初の文字だけを取得するには、Substring(0, 1)のように、開始位置「0」から抽出する長さ「1」を指定します。string res = str.Substring(0, 1);これで変数 res には文字列の1文字目だけが格納されます。サンプルコード(完全版)実際に動作するコード全体は以下
-
復号化した文字列のk番目の文字を求める方法 – Pythonでの実装
問題の概要 エンコードされた文字列では、部分文字列の繰り返しが「部分文字列+出現回数」の形式で表現されます。たとえば、文字列が pq2rs2 で k=5 の場合、復号化後の文字列は pqpqrsrs となり、5番目の文字は r です。 ここで注意したいのは、出現回数が2桁以上になるケースも存在するという点です。たとえば a12b のような入力では、「a」が12回繰り返されることを正しく読み取れる必要があります。 具体例 入力として string = pq4r2ts3、k = 11 が与えられた場合を考えてみましょう。復号化後の文字列は pqpqpqpqrrtststs となるため、11番目の