スライディングウィンドウで必要な文字を全部含む最短の部分を探す

文字列 s の中で、t の文字を数まで全部含む、いちばん短い続いた部分を探します。足りない文字の数を 1 つの数で持ち、右へ伸ばして全部そろったら左を縮める、スライディングウィンドウの練習です。

海外で定番の問題リスト 4 本には入っていません

問題

文字列 s と t を受け取ります。s の続いた部分のうち、t の文字を全部、数まで含む物 (t に同じ文字が 2 つあれば、その文字を 2 つ以上含む物) で、いちばん短い物を返す関数を書いてください。

  • そういう部分が無ければ、空の文字列 "" を返します
  • いちばん短い物が 2 つ以上あるときは、s の中でいちばん左にある物を返します
  • 英字の大文字と小文字は別の文字として扱います
  • 部分の中に、t に無い文字や、余った文字が入っていてもかまいません
  • s と t の長さは、どちらも 1 以上 100000 以下で、英字の大文字と小文字だけでできています

入力と出力の例

例 1

A、B、C を全部含む部分のうち、最後の 3 文字の "ACB" がいちばん短くなります。

s = "CXAYBZACB" t = "ABC"
"ACB"

例 2

t には N が 2 つあります。N を 2 つと A を 1 つ含む部分で最も短いのは、左から 3 文字目からの "NAN" です。

s = "BANANA" t = "ANN"
"NAN"

例 3

s の B は大文字で、t の b は小文字です。別の文字なので、含む部分はありません。

s = "aBc" t = "b"
""

面接での聞かれ方

面接では、難しい問いの代表として出されることがあります。

  • 「t の文字を全部含む、s の最小の窓を求めてください」
  • 「t に同じ文字が何個もあるときは、その数だけ要りますか?」と、範囲を自分から確かめるかを見られます
  • 「同じ長さが 2 つあったら、どちらを返しますか?」も、聞いておくと答えが 1 つに決まります

全部の部分を調べる書き方を先に口に出し、そこから「伸ばす、縮める」の窓に移ると、考えの筋が伝わります。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「配列と文字列」に、この型の要点を表とコードでまとめています。

配列と文字列の問題は、全部の組を調べると手間が大きくなる所を、窓や左右の添字で減らす形が多いです。

main.py
def min_cover(s: str, t: str) -> str:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(min_cover("CXAYBZACB", "ABC"))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します