JavaScriptで文字列をエンコードしてサイズを縮小する方法
問題
文字列 str を唯一の引数として受け取るJavaScript関数を作成します。この関数の役割は、入力文字列を特定のルールに従ってエンコードし、そのサイズを元の文字列と比較することです。そして、より小さいサイズとなった方の文字列を返します。
エンコードのルール
n[s] — 角括弧内の文字列 s が、正確に n 回繰り返されることを表します。
たとえば、「ddd」は「3[d]」とエンコードできます。しかし「3[d]」の長さは4文字である一方、「ddd」はわずか3文字です。このように、エンコードするとかえってサイズが大きくなるケースでは、元の文字列「ddd」をそのまま返すのが正しい動作となります。
入力例
const str = 'aabcaabcd';
期待される出力
const output = '2[aabc]d';
解決アプローチ: 区間DP(動的計画法)
この問題は、各部分文字列の最適なエンコード結果を段階的に求めていく区間DPで効率的に解けます。dp[i][j] には、部分文字列 s.substring(i, j + 1) の最も短くなるエンコード結果を格納していきます。
まず、すべての部分文字列について「元の文字列そのもの」を初期候補とします。
分割点 k を順にずらしながら、左側
dp[i][k]と右側dp[k + 1][j]のエンコード結果を連結し、現在の候補より短ければ更新します。さらに、その部分文字列が同じパターンの繰り返しになっていないかを調べます(
(sub + sub).indexOf(sub, 1)で最小の繰り返し単位を検出)。繰り返しが見つかれば「繰り返し回数[パターン]」の形式に圧縮し、短くなる場合のみ採用します。
これにより、入れ子になった繰り返し構造(例: 2[aabc]d)も正しく処理でき、全体として最短のエンコード結果が得られます。
実装コード
const str = 'aabcaabcd';
function encode(s) {
const { length } = s;
const dp = Array(length).fill([]);
dp.forEach((el, ind) => {
dp[ind] = Array(length).fill(null);
});
for(let l = 1; l <= length; l++){
for(let i = 0; i + l <= length; i++){
let j = i + l - 1;
dp[i][j] = s.substring(i, j + 1);
for (let k = i; k < j ; k ++) {
let acc = dp[i][k] + dp[k + 1][j];
if (acc.length < dp[i][j].length) {
dp[i][j] = acc;
}
}
let sub = s.substring(i, j + 1);
let double = sub + sub;
let cut = double.indexOf(sub, 1);
if (cut != -1 && cut < sub.length) {
let acc = sub.length / cut + "[" + dp[i][i + cut - 1] +"]";
if (acc.length < dp[i][j].length) {
dp[i][j] = acc;
}
}
}
}
let res = dp[0][dp.length - 1];
return res;
}
console.log(encode(str));
出力
コンソールには次の結果が出力されます。
2[aabc]d
この実装の計算量は区間の組み合わせ O(n²) × 分割点の走査 O(n) で、全体として約 O(n³) です。文字列がそれほど長くない場合に、常に理論上の最短エンコードを保証できるのが大きな特徴です。
-
JavaScriptで文字の出現頻度に基づいて文字列をエンコードする方法
問題文字列 str を唯一の引数として受け取る JavaScript 関数を作成する必要があります。この関数は、入力文字列をもとに新しい文字列を生成します。元の文字列の中でその文字が1回だけ出現する場合には「(」を、2回以上出現する場合には「)」を、対応する位置に割り当てます。なお、大文字と小文字の違いは無視して判定します。例えば、関数への入力が次の場合 −入力const str = Success;出力const output = )())());考え方入力文字列「Success」を大文字小文字を区別せずに見ると、「s」は3回、「u」は1回、「c」は2回、「e」は1回出現しています。したがっ
-
Pythonでランレングスエンコーディングを実装する方法
このチュートリアルでは、Pythonを使ってランレングスエンコーディング(Run-Length Encoding)を作成する方法を解説します。与えられた文字列に対して、「文字+出現回数」という形式の新しい文字列を生成して返すプログラムです。例えば、文字列 tutorialspoint は t3u1o2r1i2a1l1s1p1n1 とエンコードされます。これは各文字とその出現回数を順に連結したもので、元の文字列に最初に出現した順序が保たれます。実装の手順run_length_encoding という名前の関数を定義します。collections.OrderedDict を使い、各文字のカウントを