LintCode刷题笔记-- InterLeaving
阅读原文时间:2023年07月09日阅读:1

标签:

动态规划

解题思路

1. 这道题最重要的是,存在三个字符串,但是并不需要两个二维矩阵来进行解,因为可以使用i+j-1来代表s3的下标,这样就可以通过i和j来遍历s3了。因为对于任何一个合法的交叉字符串都会有,s3(i+j-1)=s1(i-1) 或者s3(i+j-1) = s2(j-1)

2. 所以对于动态规划矩阵就可以在s1,s2这两个向量上进行分解,有dp[i][j], 其所代表的意义的是在s3(i+j-1)的位置上是否存在有s1(i)或者s2(j)与其相等,

3.如果结果返回true,证明是一对交叉字符串,对于矩阵中的每一个点都会存在其上方或者左方有一个点为true。因为在s3中的前一个节点会有s1或者s2中的一个点来进行匹配,也可能存在两者都相等,这样的情况中,左方和上方的解应当都为true。

4. 对于初始状态,也是最懵逼的,看答案想了很久没有明白:分别遍历s1与s2,与s3进行比较,找出s1或者s2的前几项与s3。找出矩阵的入口,因为如果两个字符串为合法的交叉字符串的话,至少dp[i][0]或者dp[0][j]中至少有一个序列中存在两个true,其中dp[0][0]为true。

对于dp的解法:

s1 = a1, a2 ……..a(i-1), ai
s2 = b1, b2, …….b(j-1), bj
s3 = c1, c3, …….c(i+j-1), c(i+j)

定义 match[i][j] 意味着,S1的(0, i)和S2的(0,j),匹配与S3的(i+j)
如果 ai == c(i+j), 那么 match[i][j] = match[i-1][j], 等价于如下字符串是否匹配。

s1 = a1, a2 ……..a(i-1)
s2 = b1, b2, …….b(j-1), bj
s3 = c1, c3, …….c(i+j-1)

同理,如果bj = c(i+j), 那么match[i][j] = match[i][j-1];

5.参考代码:

public boolean isInterleave(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(); i++){
if(s1.charAt(i-1)==s3.charAt(i-1)&&dp[i-1][0]==true){
dp[i][0] = true;
}
}

    for(int j = 1; j<=s2.length(); j++){  
        if(s2.charAt(j-1)==s3.charAt(j-1)&&dp\[0\]\[j-1\]==true){  
            dp\[0\]\[j\] = true;  
        }  
    }

    for(int i = 1; i<=s1.length(); i++){  
        for(int j = 1; j<=s2.length(); j++){  
            if(s1.charAt(i-1)==s3.charAt(i+j-1)&&dp\[i-1\]\[j\]||  
               s2.charAt(j-1)==s3.charAt(i+j-1)&&dp\[i\]\[j-1\]){  
                   dp\[i\]\[j\] = true;  
               }  
        }  
    }  
    return dp\[s1.length()\]\[s2.length()\];  
}