leetcode 97 交错字符串 动态规划

给定三个字符串 s1s2s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:s = s1 + s2 + ... + sn.....

t = t1 + t2 + ... + tm    

|n - m| <= 1

交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...注意:a + b 意味着字符串 a 和 b 连接。

如果|s1|+|s2|!=|s3|,肯定不是交错字符串,在=的情况下可用动态规划,

定义f(i,j)表示s1前i个元素和s2的前j个元素是否能交错组成s3的前i+j个元素。

如果s1的第i个元素和s3的i+j个元素相等,那么s1的前i个元素和s2的前j个元素是否能交错组成 s3的前 i+j 个元素取决于 s1的前 i−1个元素和 s2的前 j 个元素是否能交错组成 s3的前 i+j−1个元素,

即此时 f(i,j) 取决于 f(i−1,j),在此情况下如果 f(i−1,j) 为真,则 f(i,j) 也为真。同样的,如果 s2的第 j 个元素和 s3的第 i+j个元素相等并且 f(i,j−1) 为真,则 f(i,j) 也为真。于是我们可以推导出这样的动态规划转移方程:

f(i,j)=[f(i−1,j) and s1 (i−1)=s3(p)]  or  [f(i,j−1)  and  s2 (j−1)=s3(p)]    其中p=i+j-1.

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出:true

分别计算所给三个字符串的长度,定义数组,大小为  前两个字符串的长度。

如果前两个字符串长度之和不等于第三个字符串,则它一定不是交错字符串,返回false;

将数组中的第一行一列元素赋值为true,遍历二维数组,利用状态转移方程。

第一次循环:

i=j=0,p=-1 不满足条件退出

第二次:

i=0,j=1,p=0;  f[0][1]  = false;

第三次:

i=0;j=2;p=1;  f[0][2] = false;

第四次:

i=0;j=3;p=2;  f[0][3]= false;

第五次:

i=0;j=4;p=3;f[0][4]=false;

第六次:

i=0;j=5;p=4;f[0][4]=false;

第一次:

i=1;j=0;p=0;f[1][0]=true;

......

f[5][5]=true;

#include <stdio.h>
#include <stdbool.h>
#include "string.h"
bool isInterleave(char* s1, char* s2, char* s3) {
    int n = strlen(s1), m = strlen(s2), t = strlen(s3);
    int f[n + 1][m + 1];
    memset(f, 0, sizeof(f));
    if (n + m != t) {
        return false;
    }
    f[0][0] = true;
    for (int i = 0; i <= n; ++i) {
        for (int j = 0; j <= m; ++j) {
            int p = i + j - 1;
            if (i > 0) {
                f[i][j] |= (f[i - 1][j] && s1[i - 1] == s3[p]);
            }
            if (j > 0) {
                f[i][j] |= (f[i][j - 1] && s2[j - 1] == s3[p]);
            }
        }
    }

    return f[n][m];
}

int main() {
    bool s;
    char *p = "aabcc";
    char *q = "dbbca";
    char *m =  "aadbbcbcac";
    s= isInterleave(p,q,m);
    printf("%d",s);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值