题目
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
判断s3是否可以有s1,s2由前向后交错取字符构成。
不难想到递归版本,但是特殊情况下:s1,s2重复较多时效率很低,必然超时。
其实即是一个子问题重复调用的问题,通过表格记录可以稍稍提高效率,即可AC。
更高效的方法dp。
flag[i][j]记录s1[i]开始、s2[j]开始的两个子串是否可以和s3[i+j]开始的子串匹配。
如果s1[i]==s3[i+j]且s1[i+1]开始、s2[j]开始的子串和s3[i+j+1]开始的子串匹配;
或者s2[j]==s3[i+j]且s1[i]开始、s2[j+1]开始的子串和s3[i+j+1]开始的子串匹配;
则s1[i]开始、s2[j]开始的两个子串可以和s3[i+j]开始的子串匹配。
由s3尾向前递推。
代码:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if(s3.size()!=s1.size()+s2.size())
return false;
vector<vector<bool>> flag(s1.size()+1,vector<bool>(s2.size()+1,false)); //s1[p1],s2[p2]开始的串可以和s3[p1+p2]开始的串匹配的标志
flag[s1.size()][s2.size()]=true; //超尾可以匹配
for(int len=1;len<=s3.size();len++) //dp,s[3]长度递增,从后向前扫描
{
for(int i=0;i<=min(len,(int)s1.size());i++) //s1使用的长度递增
{
int j=len-i; //确定s2需要的长度
if(j>s2.size())
continue;
if(i==0) //仅用s2匹配
{
if(flag[s1.size()][s2.size()-j+1]&&s2[s2.size()-j]==s3[s3.size()-len])
flag[s1.size()][s2.size()-j]=true;
}
else if(j==0) //仅用s1匹配
{
if(flag[s1.size()-i+1][s2.size()]&&s1[s1.size()-i]==s3[s3.size()-len])
flag[s1.size()-i][s2.size()]=true;
}
else if(s1[s1.size()-i]==s3[s3.size()-len]&&flag[s1.size()-i+1][s2.size()-j]) //s1[p1+1],s2[p2]可以匹配,且s1[p1]==s3[p3]
flag[s1.size()-i][s2.size()-j]=true;
else if(s2[s2.size()-j]==s3[s3.size()-len]&&flag[s1.size()-i][s2.size()-j+1]) //s1[p1],s2[p2+1]可以匹配,且s2[p2]==s3[p3]
flag[s1.size()-i][s2.size()-j]=true;
}
}
return flag[0][0];
}
};
本文介绍了一种用于判断字符串s3是否能由s1和s2交错组成的高效算法。通过使用动态规划方法,避免了递归过程中的重复计算,显著提高了算法效率。
684

被折叠的 条评论
为什么被折叠?



