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.
When you see string problem that is about subsequence or matching, dynamic programming method should come to your mind naturally.
题意很简答,就是问一下字符串可以不可以通过两个字符串交替出现得到。最自觉的方法就是DFS深度优先遍历,但是这个可能会超时(我验证过了,的确会超时)。
一般遇到字符串匹配的问题都应当想到DP动态规划。
参考代码吧,这道题很经典,很值得学习。
代码如下:
/*
* When you see string problem that is about subsequence or matching,
* dynamic programming method should come to your mind naturally.
* */
public class Solution
{
public boolean isInterleave(String s1, String s2, String s3)
{
if(s1==null || s2==null || s3==null || s1.length()+s2.length()!=s3.length())
return false;
//递归超时
//return Recursive1(s1, s2, s3, 0, 0, 0);
return byDP(s1,s2,s3);
}
/*
* When you see string problem that is about subsequence or matching,
* dynamic programming method should come to your mind naturally.
*
* 所以这道题还是用DP的思想解决。大体思路是,s1取一部分s2取一部分,
* 最后是否能匹配s3。动态规划数组是dp[i][j],表示:s1取前i位,s2取前j位,
* 是否能组成s3的前i+j位。初始化是,假设s1为空,那么s2每一位跟s3匹配放入dp[0][j];
* 假设s2为空,那么s1每一位跟s3匹配放入dp[i][0]。
* */
boolean byDP(String s1, String s2, String s3)
{
boolean [][]dp=new boolean[s1.length()+1][s2.length()+1];
dp[0][0]=true;
for(int i=1;i<s1.length()+1;i++)
{
if(s1.charAt(i-1)==s3.charAt(i-1) && dp[i-1][0])
dp[i][0]=true;
}
for(int i=1;i<s2.length()+1;i++)
{
if(s2.charAt(i-1)==s3.charAt(i-1) && dp[0][i-1])
dp[0][i]=true;
}
//遍历 DP
for(int i=1;i<s1.length()+1;i++)
{
for(int j=1;j<s2.length()+1;j++)
{
if(s3.charAt(i+j-1)==s1.charAt(i-1) && dp[i-1][j])
dp[i][j]=true;
if(s3.charAt(i+j-1)==s2.charAt(j-1) && dp[i][j-1])
dp[i][j]=true;
}
}
return dp[s1.length()][s2.length()];
}
//这是递归解法
boolean Recursive(String s1, String s2, String s3, int i, int j,int k)
{
if(i==s1.length() && j==s2.length() && k==s3.length())
return true;
else if( i<s1.length() && s3.charAt(k)==s1.charAt(i)
&& j<s2.length() && s3.charAt(k)==s2.charAt(j) )
{
if(Recursive(s1, s2, s3, i+1, j, k+1))
return true;
else
return Recursive(s1, s2, s3, i, j+1, k+1);
}
else if(i<s1.length() && s3.charAt(k)==s1.charAt(i))
return Recursive(s1, s2, s3, i+1, j, k+1);
else if(j<s2.length() && s3.charAt(k)==s2.charAt(j))
return Recursive(s1, s2, s3, i, j+1, k+1);
else
return false;
}
}
下面是C++的做做法,
当你遇到字符串匹配的时候最直觉的方法就是DP动态规划。
代码如下:
#include<iostream>
#include <vector>
using namespace std;
//当你遇到字符串匹配的时候一般都要想到DP动态规划的做法
class Solution
{
public:
bool isInterleave(string s1, string s2, string s3)
{
if (s3.length() != s1.length() + s2.length())
return false;
vector<vector<bool>> dp(s1.length()+1,vector<bool>(s2.length()+1,0));
dp[0][0] = true;
for (int i = 1; i <= s1.length(); i++)
{
if (s1[i-1] == s3[i-1] && dp[i - 1][0])
dp[i][0] = true;
}
for (int i = 1; i <= s2.length(); i++)
{
if (s2[i-1] == s3[i-1] && dp[0][i-1])
dp[0][i] = true;
}
for (int i = 1; i <= s1.length(); i++)
{
for (int j = 1; j <= s2.length(); j++)
{
if (s3[i + j - 1] == s1[i - 1] && dp[i - 1][j])
dp[i][j] = true;
if (s3[i + j - 1] == s2[j - 1] && dp[i][j-1])
dp[i][j] = true;
}
}
return dp[s1.length()][s2.length()];
}
};