AtCoder Beginner Contest 185 E - Sequence Matching 解説

やらかし反省録が増えました!!!!!!!!!!!!!!!!!!!

問題リンク

https://atcoder.jp/contests/abc185/tasks/abc185_e

問題概要

$N,\ M$ 要素からなる整数列 $A,\ B$ があります。$A,\ B$ からいくつかの要素をコスト $1$ で取り除くことができます。取り除いたあと、$A,\ B$ の要素数が同じでなくてはなりません。
取り除いたあとの $A,\ B$ について $A_i\neq B_i$ である要素があれば、その個数だけコストが $1$ ずつ上乗せされます。
コストの最小値を求めてください。

制約

$1\le N,\ M\le 1000$
$1\le A_i,\ B_i\le 10^{9}$

考察・解法

$A,\ B$ のうちそれぞれ $1$ から $i,\ j$ 要素目までを見たときのコストの最小値で DP を考えます。これを $dp_{i,\ j}$ と定義します。$i,\ j=0$ のときは、空の数列であるとします。
DP なので、初期条件及び $i,\ j$ についての遷移が分かれば良いです。

初期条件ですが、$i=0$ とすると、空の数列と $j$ 要素の数列におけるコストは $j$ なので、$dp_{0,\ j}=j$ です。$j=0$ のときも同様です。

では、$dp_{i,\ j}$ をそれまでに見た値で計算できないか考えます。
以下のように $3$ パターンに分けて説明します。

  • $A$ の最後の数を削除するとき
    コスト $1$ で可能です。よって、$dp_{i,\ j}=dp_{i-1,\ j}+1$ です。

  • $B$ の最後の数を削除するとき
    同様に、$dp_{i,\ j}=dp_{i,\ j-1}+1$ です。

  • $A,\ B$ の最後の数をどちらも残すとき
    この場合、$A_i=B_j$ であれば違う値であるときのコストは発生しないので、$dp_{i,\ j}=dp_{i-1,\ j-1}$ です。
    そうでない場合は、違う値であるときのコストが発生します。$dp_{i,\ j}=dp_{i-1,\ j-1}+1$ です。
    なお、$A_i,\ B_j$ の両方を削除することは無意味です。両方残せば高々 $1$ の追加のコストであるからです。

以上の通りの DP をすればよいです。

実装

実装を展開する
		public void Solve()
		{
			var (n, m) = cin.ReadValue<int, int>();
			var a = cin.ReadIntArray(n);
			var b = cin.ReadIntArray(m);
			var dp = new int[n + 1][];
			for (int i = 0; i < n + 1; i++)
			{
				dp[i] = new int[m + 1];
			}
			for (int i = 0; i < n + 1; i++)
			{
				dp[i][0] = i;
			}
			for (int i = 0; i < m + 1; i++)
			{
				dp[0][i] = i;
			}
 
			for (int i = 1; i <= n; i++)
			{
				for (int j = 1; j <= m; j++)
				{
					dp[i][j] = dp[i - 1][j - 1] + 1;
					if (a[i - 1] == b[j - 1]) dp[i][j]--;
					dp[i][j].Chmin(dp[i][j - 1] + 1);
					dp[i][j].Chmin(dp[i - 1][j] + 1);
				}
			}
			Console.WriteLine(dp[n][m]);
		}

ACコード: https://atcoder.jp/contests/abc185/submissions/18769369

感想

コンテスト本番やらかし案件です。ABCDF の 5 完時点では 50 位橙パフォだったのに、E が解けずずるずると水パフォまで落ちてしまいました。うわああ……。

この問題は編集距離を求める DP そのものであり、典型です。典型を典型と見抜けなかったのもまずいのですが、この程度の DP を再発明できなかった (しかも過去に類似の DP である LCS の DP で痛い目に遭っているのに!) のは、正直に言って青コーダー失格レベルだと思います。大反省です。

DP で頭が爆発することが多いし、今回も過去の教訓があったにも関わらずこれを通せなかったし、反省として、今週は DP 強化週間とします。EDPC 及び TDPC を全部埋める気でいきます。対戦よろしくお願いします。