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

Pythonで部分文字列を削除して最大スコアを求めるプログラムの解説

問題概要

文字列 s と2つの整数値 xy が与えられているとします。次の2種類の操作を任意の回数だけ実行できます。

  • 部分文字列「ab」を検索し、存在する場合はそれを削除して x ポイントを獲得する。
  • 部分文字列「ba」を検索し、存在する場合はそれを削除して y ポイントを獲得する。

これらの操作を文字列 s に適用した後、獲得できる最大ポイントを求めるのが目的です。

具体例

たとえば、入力が s = "cbbaacdeabb"、x = 4、y = 5 の場合、出力は 14 になります。その過程は以下の通りです。

  1. 初期状態の文字列は「cbbaacdeabb」。まず「cbbaacde(ab)b」のように「ab」を削除して4ポイント獲得し、文字列は「cbbaacdeb」になります。
  2. 次に「cb(ba)acdeb」のように「ba」を削除してさらに5ポイント獲得。現在のスコアは 4+5=9、文字列は「cbacdeb」です。
  3. 続いて「c(ba)cdeb」のように再び「ba」を削除して5ポイント追加。スコアは 9+5=14、文字列は「ccdeb」となります。
  4. この時点で削除できる部分文字列はもう存在しないため、最終的な答えは 14 です。

解法のアプローチ

この問題は貪欲法(グリーディ法)を用いて効率的に解くことができます。基本的な考え方は、「より高得点となるペアを優先的に削除する」というものです。具体的な手順は以下の通りです。

  • a := 'a'、b := 'b' として初期化します。
  • ans := 0、a_st := 0、b_st := 0 として初期化します(a_st と b_st はそれぞれ未処理の 'a' と 'b' のカウンタです)。
  • y > x の場合、a と b を入れ替え、x と y も入れ替えます。これにより、常に得点の高いペア(x 点)から優先的に処理できるようになります。
  • 文字列 s 内の各文字 c について、以下を繰り返します。
    • c が a と等しい場合:a_st を1増やします。
    • c が b と等しい場合:a_st が0でなければ、ans に x を加算して a_st を1減らします(高得点ペアを即座に消費)。a_st が0の場合は b_st を1増やします。
    • それ以外の文字の場合:ans に y × min(a_st, b_st) を加算し、a_st と b_st を0にリセットします(区切り文字によって残ったペアを低得点で処理します)。
  • 最終的に ans + y × min(a_st, b_st) を返します。

実装例

理解を深めるために、以下のPythonコードを見てみましょう。

def solve(s, x, y):
    a = 'a'
    b = 'b'
    ans = 0
    a_st = 0
    b_st = 0
    if y > x:
        a, b = b, a
        x, y = y, x
    for c in s:
        if c == a:
            a_st += 1
        elif c == b:
            if a_st:
                ans += x
                a_st -= 1
            else:
                b_st += 1
        else:
            ans += y * min(a_st, b_st)
            a_st = 0
            b_st = 0
    return ans + y * min(a_st, b_st)

s = "cbbaacdeabb"
x = 4
y = 5
print(solve(s, x, y))

入力

"cbbaacdeabb", 4, 5

出力

14

まとめ

このアルゴリズムは文字列を一度走査するだけで済むため、時間計算量は O(n)、空間計算量も O(1) と非常に効率的です。得点の高いペアを優先的に削除する貪欲な戦略により、常に最大スコアを達成できる点がポイントです。

  1. Pythonで文字列からn番目の文字を削除するプログラムの書き方

    はじめにこの記事では、以下の問題に対する解決方法を解説します。問題文 − 与えられた文字列から、指定したインデックス(i番目)の文字を削除し、その結果を表示します。Pythonの文字列では、インデックスは必ず0から始まるという点に注意してください。例えば、「Tutorialspoint」という文字列の場合、各文字のインデックスは以下のように対応しています。T u t o r i a l s p o i n t 0 1 2 3 4 5 6 7 8 9 10 11 12 13それでは、この問題を解決するためのPythonスクリプトを見ていきましょう。実装例def remove(string

  2. Pythonで文字列からn番目の文字を削除する方法【サンプルコード付き】

    Pythonにおいて、文字列は文字の配列として扱われます。そのため、先頭の文字のインデックスは「0」から始まり、各文字の位置(インデックス)を簡単に取得できます。この性質を利用すると、指定したn番目の文字だけを削除することが可能です。 基本的な考え方はシンプルです。削除したい文字のインデックス番号を受け取り、元の文字列を次の2つの部分文字列に分割します。 n番目のインデックスの文字より前の部分 n番目のインデックスの文字より後の部分 その後、この2つの部分文字列を連結すれば、n番目の文字が取り除かれた新しい文字列が完成します。 実行例 入力: python 削除するインデックス: 3 出