给定三个字符串 s1、s2、s3,请你帮忙验证 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;
}