我是靠谱客的博主 怕黑石头,最近开发中收集的这篇文章主要介绍字符串的交错组成,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

字符串的交错组成

题目描述

给定三个字符串str1、str2 和aim,如果aim包含且仅包含来自str1和str2的所有字符,而且在aim中属于str1的字符之间保持原来在str1中的顺序属于str2的字符之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现一个函数,判断aim是否是str1和str2交错组成,如果是请输出“YES”,否则输出“NO”。

输入描述:

输出三行,分别表示三个字符串 s t r 1 str1 str1 s t r 2 str2 str2 a i m aim aim 1 ≤ l e n g t h ( s t r 1 ) , l e n g t h ( s t r 2 ) ≤ 5000 , 1 ≤ l e n g t h ( a i m ) ≤ 10000 1 leq lengthleft ( str1 right ),lengthleft ( str2 right ) leq 5000 ,1 leq lengthleft(aim right) leq10000 1length(str1),length(str2)5000,1length(aim)10000, length()length()表示字符串长度。

输出描述:

输出“YES”或者“NO”。(不包含引号)

示例1
输入
AB
12
1AB2
输出
YES
示例2
输入
2019
9102
22001199
输出
NO
备注:

时间复杂度 O ( n ∗ m ) Oleft( n*m right) O(nm),空间复杂度 O ( m i n ( n , m ) ) Oleft( min(n,m) right) O(min(n,m))。(n表示字符串str1长度,m表示s字符串tr2长度)


题解:

又是明显的二维 dp ,设为 F[i, j] ,其含义是:aim[0…i+j-1] 能否被 str1[0…i-1] 和 str2[0…j-1] 交错组成。F[i, j] 有三种情况:

  • 如果 F[i-1, j] 为 true 并且 str1[i-1] = aim[i+j-1] ,则 F[i, j] 为 true;
  • 如果 F[i, j-1] 为 true 并且 str2[j-1] = aim[i+j-1],则 F[i, j] 为 true;
  • 不满足上面两种情况,则 F[i, j] 为 false。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 5010;
char str1[N];
char str2[N];
char aim[N << 1];
bool f[N][N];
int main(void) {
scanf("%s", str1);
scanf("%s", str2);
scanf("%s", aim);
int len1 = strlen(str1);
int len2 = strlen(str2);
int len = strlen(aim);
if (len != len1 + len2) return 0 * puts("NO");
f[0][0] = true;
for (int i = 1; i <= len1; ++i) {
if (str1[i - 1] == aim[i - 1]) f[i][0] = true;
else break;
}
for (int j = 1; j <= len2; ++j) {
if (str2[j - 1] == aim[j - 1]) f[0][j] = true;
else break;
}
for (int i = 1; i <= len1; ++i) {
for (int j = 1; j <= len2; ++j) {
if ((str1[i - 1] == aim[i + j - 1] && f[i - 1][j]) ||
(str2[j - 1] == aim[i + j - 1] && f[i][j - 1]))
f[i][j] = true;
}
}
return 0 * puts(f[len1][len2] ? "YES" : "NO");
}

滚动数组优化:

直接删掉第一维即可,但是在二重循环中,注意初始化 F[0] 的值。

滚动数组代码:
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 5010;
char str1[N];
char str2[N];
char aim[N << 1];
bool f[N];
int main(void) {
scanf("%s", str1);
scanf("%s", str2);
scanf("%s", aim);
int len1 = strlen(str1);
int len2 = strlen(str2);
int len = strlen(aim);
if (len != len1 + len2) return 0 * puts("NO");
f[0] = true;
for (int i = 1; i <= len2; ++i) {
if (str2[i - 1] != aim[i - 1]) break;
f[i] = true;
}
for (int i = 1; i <= len1; ++i) {
f[0] = f[0] && str1[i - 1] == aim[i - 1];
for (int j = 1; j <= len2; ++j) {
if ((str1[i - 1] == aim[i + j - 1] && f[j]) ||
(str2[j - 1] == aim[i + j - 1] && f[j - 1]))
f[j] = true;
else
f[j] = false;
}
}
return 0 * puts(f[len2] ? "YES" : "NO");
}
注意:

此题效率靠前的解法是不对的,那种遍历两次的解法明显可以 hack ,比如下面两种情况:

abc
abd
abcd
abc
abd
abcdef

两种情况都是 ‘NO’ ,但是按照那种遍历结果都是 ‘YES’,如有 O ( n ) O(n) O(n)解法,欢迎来讨论。

最后

以上就是怕黑石头为你收集整理的字符串的交错组成的全部内容,希望文章能够帮你解决字符串的交错组成所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部