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.
DP二维动态规划,可以用top down 也可以bottom up, optimum state 是 dp[i][j] 是否能组成s3[i+j], i 和 j分别是s1,s2的当前index.
所以,方程是 dp[i][j] = (dp[i-1][j] && (s1.charAt(i-1)==s3.charAt(i+j-1))) || (dp[i][j-1] && (s2.charAt(j-1)==s3.charAt(i+j-1)));
dp[i][j]表示s1取前i位,s2取前j位,是否能组成s3的前i+j位
举个列子,注意左上角那一对箭头指向的格子dp[1][1], 表示s1取第1位a, s2取第1位d,是否能组成s3的前两位aa
从dp[0][1] 往下的箭头表示,s1目前取了0位,s2目前取了1位,我们添加s1的第1位,看看它是不是等于s3的第2位,( i + j 位)
从dp[1][0] 往右的箭头表示,s1目前取了1位,s2目前取了0位,我们添加s2的第1位,看看它是不是等于s3的第2位,( i + j 位)
// iterator DP
public static boolean isInterleave2(String s1, String s2, String s3){
if(s1.length() + s2.length()!=s3.length()) return false;
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][0] = true;
for(int i = 1; i < s2.length()+1; i++) if(s2.charAt(i-1) == s3.charAt(i-1)) dp[0][i] = true;
for(int i = 1; i < dp.length; i++){
for(int j = 1; j < dp[0].length; j++){
if(dp[i][j-1] && s2.charAt(j-1)== s3.charAt(i+j-1)) dp[i][j] = true;
if(dp[i-1][j] && s1.charAt(i-1) == s3.charAt(i+j-1)) dp[i][j] = true;
}
}
return dp[s1.length()][s2.length()];
}
或者:
// recursive DP
public static boolean isInterleave(String s1, String s2, String s3){
int[][] dp = new int[s1.length()+1][s2.length()+1];
return isInterleaveHelper(s1,s2,s3,0,0,0, dp);
}
private static boolean isInterleaveHelper(String s1, String s2, String s3, int i, int j, int k, int[][] dp){
if(k ==s3.length()){
if( i==s1.length() && j ==s2.length()) return true;
return false;
}
char c = s3.charAt(k);
if(dp[i][j] ==1) return true;
if(dp[i][j] ==2) return false;
boolean result = (i<s1.length() &&s1.charAt(i) == c?isInterleaveHelper(s1,s2,s3,i+1,j,k+1,dp):false) || (j<s2.length() && s2.charAt(j) == c?isInterleaveHelper(s1,s2,s3,i,j+1,k+1,dp):false);
dp[i][j] = result?1:2;
return result;
}