题目描述:
给定三个字符串 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
连接。
解题思路:
第一个想到的就是贪心算法,轮流遍历s1,s2,哪个能匹配得上s3,就index++
但显然会存在s1,s2某一段相同的情况,这时候就需要记录index,在选择遍历s1但后面不匹配时,退回到该index。
本以为贪心+回溯可以解决,实际写了之后发现,会在第99个例子超时。
bool isInterleave(string s1, string s2, string s3) {
if(s1.size()+s2.size() != s3.size()) return false;
return dfs(0,0,0,s1,s2,s3);
}
bool dfs(int i,int j,int k, string s1, string s2, string s3){
if(k>=s3.size()) return true;
bool res = false;
if(i<s1.size() && s1[i]==s3[k]) res |= dfs(i+1,j,k+1,s1,s2,s3);
if(res) return res;
if(j<s2.size() && s2[j]==s3[k]) res |= dfs(i,j+1,k+1,s1,s2,s3);
return res;
}
所以还是动态规划吧。
f[i][j] 表示s3[0......i+j-1] 与s1[0......i-1] s2[0......j-1]交错匹配成功
所以状态转移方程是 f[i][j] = (s1[i-1]==s3[i+j-1] && f[i-1][j]) || (s2[j-1]==s3[i+j-1] && f[i][j-1])
bool isInterleave(string s1, string s2, string s3) {
int m = s1.size(), n = s2.size();
if(m+n != s3.size()) return false;
vector<vector<bool>> f(m+1,vector<bool>(n+1,false));
f[0][0] = true;
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
if(i>0){
f[i][j] = f[i][j] | (s1[i-1]==s3[i+j-1] && f[i-1][j]);
}
if(j>0){
f[i][j] = f[i][j] | (s2[j-1]==s3[i+j-1] && f[i][j-1]);
}
}
}
return f[m][n];
}