字符串的交错组成

【题 目】
给定三个字符串str1、str2和aim。如果aim包含且仅包含来⾃自str1和str2的所有字
符,⽽而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符
之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现⼀一个函
数,判断aim是否是str1和str2交错组成。
【举例】
str1=“AB”,str2=“12”。那么“AB12”、“A1B2”、“A12B”、“1A2B”和“1AB2”等等都
是str1和str2交错组成。
【难度】
校★★★☆
【解答】
如果str1的⻓长度为M,str2的⻓长度为N,经典动态规划的⽅方法可以达到时间复杂度O(M*N),额
外空间复杂度O(M*N)。如果结合空间压缩的技巧可以把额外空间复杂度减⾄至O(min{M,N})。
先来介绍经典动态规划的⽅方法。⾸首先aim如果是str1和str2的交错组成,aim的⻓长度⼀一定是M
+N,否则直接返回false。然后⽣生成⼤大⼩小为(M+1)*(N+1)布尔类型的矩阵dp,dp[i][j]的值代表
aim[0..i+j-1]能否被str1[0..i-1]和str2[0..j-1]交错组成。计算dp矩阵的时候,是从左到右再
从上到下的计算的,dp[M][N]也就是dp矩阵中最右下⾓角的值,就表⽰示aim整体能否被str1整
体和str2整体交错组成,也就是最终结果。具体说明dp矩阵每个位置的值是如何计算。
1,dp[0][0]=true。aim为空串时,当然可以被str1为空串和str2为空串交错组成。
2,矩阵dp第⼀一列即dp[0..M-1][0]。dp[i][0]表⽰示aim[0..i-1]能否只被str1[0..i-1]交错组成。
如果aim[0..i-1]等于str1[0..i-1],则令dp[i][0]=true,否则令dp[i][0]=false。
3,矩阵dp第⼀一⾏行即dp[0][0..N-1]。dp[0][j]表⽰示aim[0..j-1]能否只被str2[0..j-1]交错组成。
如果aim[0..j-1]等于str1[0..j-1],则令dp[i][0]=true,否则令dp[i][0]=false。
4,对于其他位置(i,j),dp[i][j]的值由下⾯面的情况决定。
1)dp[i-1][j]代表aim[0..i+j-2]能否被str1[0..i-2]和str2[0..j-1]交错组成,如果可以,
那么如果再有str1[i-1]等于aim[i+j-1],说明str1[i-1]⼜又可以作为交错组成aim[0..i+j-1]的最
后⼀一个字符。令dp[i][j]=true。
2)dp[i][j-1]代表aim[0..i+j-2]能否被str1[0..i-1]和str2[0..j-2]交错组成,如果可以,
那么如果再有str2[j-1]等于aim[i+j-1],说明str1[j-1]⼜又可以作为交错组成aim[0..i+j-1]的最
后⼀一个字符。令dp[i][j]=true。

3)如果情况1)和情况2)都不满⾜足,令dp[i][j]=false。

#include<vector>
using namespace std;
class Mixture {
public:
    bool chkMixture(string A, int n, string B, int m, string C, int v) {
        // write code here
       if(n+m!=v) return false;
        vector<bool> dp;
        string shorts,longs,aim;
        aim = C;
        if(n<m) {dp = vector<bool>(n+1,false);shorts = A;longs = B;}
        else {dp = vector<bool>(m+1,false);shorts = B;longs = A;}
       dp[0] = true;
       for(int i = 1;i<=shorts.size();i++){
           if(shorts[i-1]!=aim[i-1]){
               break;
           }
           dp[i] = true;
       }
        for (int i = 1; i <= longs.size(); i++) {
           for (int j = 1; j <= shorts.size(); j++) {
                if ((longs[i - 1] == aim[i + j - 1] && dp[j])
                || (shorts[j - 1] == aim[i + j - 1] && dp[j - 1])) {
                    dp[j] = true;
                    } else {
                        dp[j] = false;
                    }
           }
        }
        return dp[shorts.size()];
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值