Dynamic Programing about String

Dynamic Programing about String

对于两个字符串之间的关系,有很多题目可以用动态规划的思想解答。关键是要找到两个字符串之间的状态转移方程。此处可以使用一个二维矩阵,找出两个字符串的前缀之间的关系,从而推出两个字符串之间的关系。

下面以LeetCode上面Interleaving String为例。

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

例如s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac",结果为True,而s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc",结果为False

我们采用bool型二维数组interleaveinterleave[i][j]代表s1的前i个字符与s2的前j个字符进行插入操作,能否得到s3的前i+j个字符。我们考虑以下几个情况:

  1. 如果interleave[i-1][j]interleave[i][j-1]都为False,说明无论是s1的第i个字符还是s2的第j个字符都无法作为s3的末尾字符,此时interleave[i][j]必然为False。
  2. 除此之外,如果interleave[i-1][j] == True,说明s1[:i-1]能插入s2[:j]中得到s3[:i-1+j]。如果s1第i个字符等于s3的第i+j个字符,则interleave[i][j] = True
  3. 除此之外,则interleave[i][j-1]必然True,说明s1[:i]能插入s2[:j-1]中得到s3[:i-1+j]。如果s2第j个字符等于s3的第i+j个字符,则interleave[i][j] = True

我们可以得到状态转移方程如下

$$
interleave[i][j] =
\begin{cases}
False \quad & interleave[i-1][j] == False \wedge \\ \quad & interleave[i][j-1] == False \\
s2[j-1] == s3[i+j-1] \quad & interleave[i][j-1] == True \\
s1[i-1] == s3[i+j-1] \quad & otherwise
\end{cases}
$$

对于边界条件,例如interleave[i][0]即代表着s1[:i]是否为s3[:i],则interleave[i][0] = interleave[i-1][0] and s1[i-1] == s3[i-1],同理interleave[0][i] = interleave[0][i-1] and s2[i-1] == s3[i-1]。最终interleave[len(s1)][len(s2)]即为所求。

原题例一的状态转移矩阵如下所示。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×