97. 交错字符串
给定三个字符串 s1
、s2
、s3
,请你帮忙验证 s3
是否是由 s1
和 s2
交错 组成的。
两个字符串 s
和 t
交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:
s = s1 + s2 + ... + sn
t = t1 + t2 + ... + tm
|n - m| <= 1
- 交错 是
s1 + t1 + s2 + t2 + s3 + t3 + ...
或者t1 + s1 + t2 + s2 + t3 + s3 + ...
注意:a + b
意味着字符串 a
和 b
连接。
示例 1:
输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" 输出:true
示例 2:
输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" 输出:false
思路一:
首先想到双指针的方法,从s1,s2对s3进行字符逐个匹配,并且需要进行回溯(考虑该字符匹配给s1、s2两种情况)。
1.dfs结束情况:
s3的size为空时
2.递归
将当前s3[i]匹配给s1后,递归s1.substr(s1Index+1),s2,s3.substr(i+1)),匹配给s2也类似
class Solution {
public:
bool dfs(const string& s1,const string& s2,const string& s3){
if(s1.size()+s2.size()!=s3.size()) return false;
else if(s3.size()==0) return true;
int s1Index=0,s2Index=0;
for(int i=0;i<s3.size();i++)
{
if(s1Index<s1.size()&&s1[s1Index]==s3[i])
{
//当前i匹配给s1
if(dfs(s1.substr(s1Index+1),s2,s3.substr(i+1))) return true;
}
if(s2Index<s2.size()&&s2[s2Index]==s3[i])
{
//当前i匹配给s2
if(dfs(s1,s2.substr(s2Index+1),s3.substr(i+1))) return true;
}
else return false;
}
return true;
}
bool isInterleave(string s1, string s2, string s3) {
return dfs(s1,s2,s3);
}
};
能通过测试的部分情况,但提交后有内存限制
思路二:
动态规划
1.dp状态描述:定义dp[i][j]表示s1前i个 s2前j个字符能否与s3 i+j个字符匹配成功
2.递推公式:
dp[i][j]主要有两种情况,1.新元素分配给s1 2.新元素分配给s2
dp[i][j]=( dp[i-1][j] && s3[i+j-1]==s1[i-1]) || ( dp[i][j-1] && s3[i+j-1]==s2[j-1] )
3.初始状态:dp[0][0](s1 s2 s3 都为空时)
dp[i][0] s1单独与s3是否完全匹配
dp[0][j] s2单独与s3是否完全匹配
4.返回值dp[s1.size()][s2.size()]
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size()!=s3.size()) return false;
else if(s3.size()==0) return true;
else if(s1.size()==0) return s2==s3;
else if(s2.size()==0) return s1==s3;
//定义dp[i][j]表示s1前i个 s2前j个字符能否与s3 i+j个字符匹配成功
//递推公式:第i+j个字符匹配给s1[i]或s2[j]且dp[i-1][j]或dp[i][j-1]要是true
//dp[i][j]=( dp[i-1][j] && s3[i+j-1]==s1[i-1]) || ( dp[i][j-1] && s3[i+j-1]==s2[j-1] )
vector<vector<bool>> dp(s1.size()+1,vector<bool>(s2.size()+1,false));
dp[0][0]=true;
//如果有匹配不上,那整行或列都是false
for(int i=1;i<=s1.size();i++)
{
dp[i][0]= s1[i-1]==s3[i-1];
if(!dp[i][0]) break;
}
for(int i=1;i<=s2.size();i++)
{
dp[0][i]= s2[i-1]==s3[i-1];
if(!dp[0][i]) break;
}
for(int i=1;i<=s1.size();i++)
{
for(int j=1;j<=s2.size();j++)
{
dp[i][j]=( dp[i-1][j] && s3[i+j-1]==s1[i-1]) || ( dp[i][j-1] && s3[i+j-1]==s2[j-1] );
}
}
return dp[s1.size()][s2.size()];
}
};