C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】予算以内で等しくなる部分文字列の最大長を求める方法

問題の概要

同じ長さを持つ2つの文字列 s と t が与えられます。私たちの目標は、s を t に変更することです。

s の i 番目の文字を t の i 番目の文字に変更する際のコストは、|s[i] - t[i]|、つまり2つの文字のASCIIコード値の差の絶対値として定義されます。さらに整数 maxCost が与えられているので、合計コストが maxCost 以下という条件を満たしながら、s の部分文字列を t の対応する部分文字列と同一に変換するとき、その最大の長さを求めなければなりません。

例えば、入力が s = "abcd"、t = "bcdf"、maxCost = 3 の場合を考えてみましょう。s の "abc" を "bcd" に変換すると、各文字の変換コストはそれぞれ 1 + 1 + 1 = 3 となり、ちょうど maxCost 以内に収まります。したがって、出力は 3 になります。

解決のアプローチ

この問題はスライディングウィンドウ(尺取り法)を使うことで、効率的に解くことができます。ウィンドウの合計コストが maxCost を超えたら左端を縮め、常に条件を満たす最長の区間を追跡します。

具体的な手順は以下の通りです。

  • j := 0、sum := 0、ret := 0 で初期化する
  • i を 0 から s と t のサイズのうち小さい方までループする
    • sum に |s[i] − t[i]| を加算する
    • sum > maxCost である間、次を繰り返す
      • sum から |s[j] − t[j]| を減算する
      • j を 1 増やす
    • ret := max(ret, i − j + 1) で最大長を更新する
  • 最後に ret を返す

C++での実装例

それでは、実際のコードを見て理解を深めましょう。

class Solution {
public:
   int equalSubstring(string s, string t, int maxCost) {
      int j = 0;
      int sum = 0;
      int ret = 0;
      for(int i = 0; i < min((int)s.size(), (int)t.size()); i++){
         sum += abs(s[i] - t[i]);
         while(sum > maxCost){
            sum -= abs(s[j] - t[j]);
            j++;
         }
         ret = max(ret, i - j + 1);
      }
      return ret;
   }
};

入力例

"abcd"
"bcdf"
3

出力例

3

計算量について

このアルゴリズムでは、インデックス i と j がそれぞれ文字列を高々一度ずつ走査するだけなので、時間計算量は O(n)、使用する追加メモリは定数個の変数のみで O(1) となります。文字数が多い大きな入力に対しても高速に動作する、非常に効率的な解法です。

  1. C++で二分木を等しい合計値の2つの木に分割できるか判定する方法

    問題概要n 個のノードを持つ二分木が与えられたとき、元の木からちょうど1本の辺を削除することで、その木を「ノード値の合計が等しい2つの木」に分割できるかどうかを判定するのがこの問題です。例えば、次のような入力が与えられたとします。この場合、出力は true になります。解法のアプローチこの問題は、各部分木の合計値を事前にすべて計算しておき、その中に「木全体の合計の半分」と一致する値が存在するかを確認することで解けます。手順は以下の通りです。部分木の合計値を格納するためのスタック st を用意します。solve() 関数を定義します。引数としてノードを受け取ります。ノードが null の場合は

  2. C++でPOSIXコマンドを実行して出力を取得する方法

    C++のプログラム内からPOSIXコマンドを実行したい場面は少なくありません。実はその方法は非常にシンプルで、標準ライブラリが提供する system() 関数を使うだけで実現できます。この関数に文字列としてコマンドを渡すと、シェルを介してそのPOSIXコマンドが実行されます。system() 関数の基本構文system(command)引数には実行したいコマンドを表す文字列を渡します。戻り値として、コマンドの終了ステータスが返されます(正常終了時は一般的に 0 が返ります)。サンプルコード以下は、echo コマンドで文字列を出力し、bc コマンドで数式を計算する例です。#include <