交错字符串@97.leetcode

不说废话,直戳盲点,打通思路, 举一反三。

题目描述

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出: false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/interleaving-string

先上代码

执行用时 :12 ms, 在所有 C++ 提交中击败了61.34%的用户
内存消耗 :8.7 MB, 在所有 C++ 提交中击败了42.10%的用户

bool isInterleave(string s1, string s2, string s3) {
    if(s1.size()+s2.size()!=s3.size())
        return false;
	vector<vector<bool> > dp(s1.size() + 1, vector<bool>(s2.size() + 1, false));
    dp[0][0] = true;
	for (int i = 1; i < s1.size() + 1; ++i) {
		if (s1[i - 1] == s3[i - 1] && dp[i-1][0] == true)
			dp[i][0] = true;
	}
    for(int j=1; j<s2.size()+1;++j){
        if (s2[j - 1] == s3[j - 1] && dp[0][j-1] == true)
			dp[0][j] = true;
    }
	for (int i = 1; i < s1.size()+1; ++i) {
		for (int j = 1; j < s2.size()+1; ++j) {
			if ( (dp[i - 1][j] == true && s1[i - 1] == s3[i + j - 1]) 
					|| (dp[i][j - 1] == true && s2[j - 1] == s3[i + j - 1]) )
				dp[i][j] = true;
			else
				dp[i][j] = false;
		}
	}
	return dp[s1.size()][s2.size()];
}

算法思路

这是一个动态规划问题,所以我们要先得到状态转移方程

  1. 定义状态 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 s 1 [ 1 : i ] s_1[1:i] s1[1:i], s 2 [ 1 : j ] s_2[1:j] s2[1:j] 能否交错组成 s 3 [ 1 : i + j ] s_3[1:i+j] s3[1:i+j], 那么 d p [ n ] [ n ] dp[n][n] dp[n][n]就是我们想要的结果。
  2. 可得转移方程: d p [ i ] [ j ] = { T r u e d p [ i − 1 ] [ j ] = T r u e A N D s 1 [ i ] = s 3 [ i + j ] T r u e d p [ i ] [ j − 1 ] = T r u e A N D s 2 [ j ] = s 3 [ i + j ] F a l s e O t h e r s dp[i][j]=\left\{ \begin{array}{rcl} True &amp; &amp; {dp[i-1][j]=True}&amp;{AND}&amp;{s_1[i]=s_3[i+j]} \\ True &amp; &amp; {dp[i][j-1]=True}&amp;{AND}&amp;{s_2[j]=s_3[i+j]}\\ False &amp; &amp; {Others} \end{array} \right. dp[i][j]=TrueTrueFalsedp[i1][j]=Truedp[i][j1]=TrueOthersANDANDs1[i]=s3[i+j]s2[j]=s3[i+j]
  3. 状态转移方程的第一条的含义可以这样理解, 如果 s 1 [ 1 : i − 1 ] s_1[1:i-1] s1[1:i1] s 2 [ 1 : j ] s_2[1:j] s2[1:j]能交错组成 s 3 [ i + j − 1 ] s_3[i+j-1] s3[i+j1], 那么当 s 1 [ i ] = s 3 [ i + j ] s_1[i]=s_3[i+j] s1[i]=s3[i+j]时,则 s 1 [ 1 : i ] s_1[1:i] s1[1:i] s 2 [ 1 : j ] s_2[1:j] s2[1:j]可以表示 s 3 [ 1 : i + j ] s_3[1:i+j] s3[1:i+j],这是递推为True的一个条件,第二条原理类似。
  4. 为了更好的表达状态转移方程是如何进行的,我们用表格表示它:
\012345
0TF
1T
2
3
4
5

值得注意的是,我们不能从 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0] 开始表示 s 1 [ 0 ] s_1[0] s1[0] s 2 [ 0 ] s_2[0] s2[0]能不能交错组成 s 3 [ 0 : 1 ] s_3[0:1] s3[0:1],因为字符应该一个一个的去加入考虑,如果从 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0]开始考虑,那么一开始就得考虑两个字符。为了方便的去表示, d p [ 0 ] [ 0 ] dp[0][0] dp[0][0]直接设置为True,表示 s 1 s_1 s1 s 2 s_2 s2都没有开始进入考虑时的状态,然后一切从 d p [ 0 ] [ 1 ] dp[0][1] dp[0][1] d p [ 1 ] [ 0 ] dp[1][0] dp[1][0]开始。

  1. 每个格子表示一个状态,再细看状态转移方程,两个条件分别是从当前格子的上方和左方去考虑,以 d p [ 1 ] [ 1 ] dp[1][1] dp[1][1]为例,两个条件分别考虑 d p [ 0 ] [ 1 ] dp[0][1] dp[0][1] d p [ 1 ] [ 0 ] dp[1][0] dp[1][0]是否为True下的情况,继而结合 s 1 [ 1 ] s_1[1] s1[1]或者 s 2 [ 1 ] s_2[1] s2[1]是否与 s 3 [ 1 ] s_3[1] s3[1]对应。所以,我们要想使得状态持续转移下去,每次计算状态的时候,要保证左方和上方的格子已经有结果。
  2. 我们可以很方便的得先到第一行,与第一列的结果,然后通过简单的嵌套循环就可以依次递推,详细的可以看代码。

学习和总结

  • 二维状态不仅要弄清楚状态转移方程,更要弄清楚状态转移方程得以运行的机制。可以画表格来更加只管一些。
  • 映像中相似的题目:通配符匹配.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值