leetcode:交错字符串

https://leetcode-cn.com/problems/interleaving-string/

DFS:

可能大家想的第一种方法就是挨个挨个的去比较,设置三个指针,i,j,k,如果s1的第一个元素和s3的第一个元素相等,则i和k都要后移一位,就这样比较下去,直到 所有指针都到达最后,就说明是交错字符串。但是有个很坑的地方,如果s1和s2指针所指的元素都和s3的目标元素相同,那么这时候面临两种选择,但是这样就会得出错误的答案。样例1的那个就会出错。

但是,我们还是想要用那种办法,我就可以用深搜,分别去递归两种情况,如果不成功,就回溯过来,选择另一种方式。

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        return f(s1, 0, s2, 0, s3, 0);
    }
    //i,j,k分别指向s1,s2和s3的指针.
    private boolean f(String s1, int i, String s2, int j, String s3, int k){
        if(s1.length() + s2.length() != s3.length())
            return false;
        if(i == s1.length() && j == s2.length() && k == s3.length())//成功,退出
            return true;
        if(i == s1.length()){//s1或者s2其中一个遍历完了,就只需要遍历另一个就行了
            while (j < s2.length()){
                if(s2.charAt(j) != s3.charAt(k))
                    return false;
                j++;
                k++;
            }
            return true;
        }
        if(j == s2.length()){
            while (i < s1.length()){
                if(s1.charAt(i) != s3.charAt(k))
                    return false;
                i++;
                k++;
            }
            return true;
        }
        //碰到相同的情况,两种情况都试一下
        if(s1.charAt(i) == s3.charAt(k)){
            if(f(s1, i + 1, s2, j, s3, k + 1))
                return true;
        }
        if(s2.charAt(j) == s3.charAt(k)){
            if(f(s1, i, s2, j + 1, s3, k + 1))
                return true;
        }
        return false;
    }
}

动态规划:

利用动态规划的思想,s1的前i个元素和s2的前j个元素,能否组成s3的前i+j个元素,取决于s1的前i-1个元素和s2的前j个元素,能否组成s3的前i+j-1个元素,并且s1的第i个元素等于s3的第i+j个元素。同理s2的前j-1个元素也一样。

设一个二维数组dp[i][j]表示s1的前i个元素和s2的前j个元素,能否组成s3的前i+j个元素。

状态转移方程:dp[i][j] = (dp[i - 1][j] && s3(i + j - 1) = s1(i - 1)) || (dp[i][j - 1] && s3(i + j - 1) = s2(j - 1));

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int l1 = s1.length(),l2 = s2.length(),l3 = s3.length();
        if(l1 + l2 != l3) return false;
        boolean[][] dp = new boolean[l1+1][l2+1];
        dp[0][0] = true;
        //i或者j为0的时候单独考虑
        for (int i = 1; i <= l1; i++) {
            if(s1.charAt(i - 1) == s3.charAt(i - 1)) dp[i][0] = dp[i-1][0];
        }
        for (int i = 1; i <= l2 ; i++) {
            if(s2.charAt(i - 1) == s3.charAt(i - 1)) dp[0][i] = dp[0][i-1];
        }
        for (int i = 1; i <= l1; i++) {
            for (int j = 1; j <=l2 ; j++) {
                dp[i][j] = (dp[i - 1][j] && s3.charAt(i + j - 1) == s1.charAt(i - 1))
                        || (dp[i][j - 1] && s3.charAt(i + j - 1) == s2.charAt(j - 1));
            }
        }
        return dp[l1][l2];
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值