iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++怎么解决交织相错的字符串问题
  • 924
分享到

C++怎么解决交织相错的字符串问题

2023-06-19 13:06:25 924人浏览 安东尼
摘要

这篇文章主要介绍“c++怎么解决交织相错的字符串问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++怎么解决交织相错的字符串问题”文章能帮助大家解决问题。交织相错的字符串Given s

这篇文章主要介绍“c++怎么解决交织相错的字符串问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++怎么解决交织相错的字符串问题”文章能帮助大家解决问题。

交织相错的字符串

Given s1s2s3, find whether s3 is fORMed by the interleaving of s1 and s2.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" Output: false


这道求交织相错的字符串和之前那道 Word Break 的题很类似,就像我之前说的只要是遇到字符串的子序列或是匹配问题直接就上动态规划 Dynamic Programming,其他的都不要考虑,什么递归呀的都是浮云(当然带记忆数组的递归写法除外,因为这也可以算是 DP 的一种),千辛万苦的写了递归结果拿到 OJ 上妥妥 Time Limit Exceeded,能把人气昏了,所以还是直接就考虑 DP 解法省事些。一般来说字符串匹配问题都是更新一个二维 dp 数组,核心就在于找出状态转移方程。那么我们还是从题目中给的例子出发吧,手动写出二维数组 dp 如下:

  Ø d b b c a
Ø T F F F F F
a T F F F F F
a T T T T T F
b F T T F T F
c F F T T T T
c F F F T F T

首先,这道题的大前提是字符串 s1 和 s2 的长度和必须等于 s3 的长度,如果不等于,肯定返回 false。那么当 s1 和 s2 是空串的时候,s3 必然是空串,则返回 true。所以直接给 dp[0][0] 赋值 true,然后若 s1 和 s2 其中的一个为空串的话,那么另一个肯定和 s3 的长度相等,则按位比较,若相同且上一个位置为 True,赋 True,其余情况都赋 False,这样的二维数组 dp 的边缘就初始化好了。下面只需要找出状态转移方程来更新整个数组即可,我们发现,在任意非边缘位置 dp[i][j] 时,它的左边或上边有可能为 True 或是 False,两边都可以更新过来,只要有一条路通着,那么这个点就可以为 True。那么我们得分别来看,如果左边的为 True,那么我们去除当前对应的 s2 中的字符串 s2[j - 1] 和 s3 中对应的位置的字符相比(计算对应位置时还要考虑已匹配的s1中的字符),为 s3[j - 1 + i], 如果相等,则赋 True,反之赋 False。 而上边为 True 的情况也类似,所以可以求出状态转移方程为:

dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j]) || (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i]);

其中 dp[i][j] 表示的是 s2 的前 i 个字符和 s1 的前 j 个字符是否匹配 s3 的前 i+j 个字符,根据以上分析,可写出代码如下:

解法一:

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        if (s1.size() + s2.size() != s3.size()) return false;        int n1 = s1.size(), n2 = s2.size();        vector<vector<bool>> dp(n1 + 1, vector<bool> (n2 + 1));         dp[0][0] = true;        for (int i = 1; i <= n1; ++i) {            dp[i][0] = dp[i - 1][0] && (s1[i - 1] == s3[i - 1]);        }        for (int i = 1; i <= n2; ++i) {            dp[0][i] = dp[0][i - 1] && (s2[i - 1] == s3[i - 1]);        }        for (int i = 1; i <= n1; ++i) {            for (int j = 1; j <= n2; ++j) {                dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j]) || (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i]);            }        }        return dp[n1][n2];    }};

我们也可以把for循环合并到一起,用if条件来处理边界情况,整体思路和上面的解法没有太大的区别,参见代码如下:

解法二:

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        if (s1.size() + s2.size() != s3.size()) return false;        int n1 = s1.size(), n2 = s2.size();        vector<vector<bool>> dp(n1 + 1, vector<bool> (n2 + 1, false));         for (int i = 0; i <= n1; ++i) {            for (int j = 0; j <= n2; ++j) {                if (i == 0 && j == 0) {                    dp[i][j] = true;                } else if (i == 0) {                    dp[i][j] = dp[i][j - 1] && s2[j - 1] == s3[i + j - 1];                } else if (j == 0) {                    dp[i][j] = dp[i - 1][j] && s1[i - 1] == s3[i + j - 1];                } else {                    dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1]) || (dp[i][j - 1] && s2[j - 1] == s3[i + j - 1]);                }            }        }        return dp[n1][n2];    }};

这道题也可以使用带优化的 DFS 来做,我们使用一个 HashSet,用来保存匹配失败的情况,我们分别用变量i,j,和k来记录字符串 s1,s2,和 s3 匹配到的位置,初始化的时候都传入0。在递归函数中,首先根据i和j,算出 key 值,由于我们的 HashSet 中只能放一个数字,而我们要 encode 两个数字i和j,所以通过用i乘以 s3 的长度再加上j来得到 key,此时我们看,如果 key 已经在集合中,直接返回 false,因为集合中存的是无法匹配的情况。然后先来处理 corner case 的情况,如果i等于 s1 的长度了,说明 s1 的字符都匹配完了,此时 s2 剩下的字符和 s3 剩下的字符可以直接进行匹配了,所以我们直接返回两者是否能匹配的 bool 值。同理,如果j等于 s2 的长度了,说明 s2 的字符都匹配完了,此时 s1 剩下的字符和 s3 剩下的字符可以直接进行匹配了,所以我们直接返回两者是否能匹配的 bool 值。如果 s1 和 s2 都有剩余字符,那么当 s1 的当前字符等于 s3 的当前字符,那么调用递归函数,注意i和k都加上1,如果递归函数返回 true,则当前函数也返回 true;还有一种情况是,当 s2 的当前字符等于 s3 的当前字符,那么调用递归函数,注意j和k都加上1,如果递归函数返回 true,那么当前函数也返回 true。如果匹配失败了,则将 key 加入集合中,并返回 false 即可,参见代码如下:

解法三:

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        if (s1.size() + s2.size() != s3.size()) return false;        unordered_set<int> s;        return helper(s1, 0, s2, 0, s3, 0, s);    }    bool helper(string& s1, int i, string& s2, int j, string& s3, int k, unordered_set<int>& s) {        int key = i * s3.size() + j;        if (s.count(key)) return false;        if (i == s1.size()) return s2.substr(j) == s3.substr(k);        if (j == s2.size()) return s1.substr(i) == s3.substr(k);        if ((s1[i] == s3[k] && helper(s1, i + 1, s2, j, s3, k + 1, s)) ||             (s2[j] == s3[k] && helper(s1, i, s2, j + 1, s3, k + 1, s))) return true;        s.insert(key);        return false;    }};

既然 DFS 可以,那么 BFS 也就坐不住了,也要出来浪一波。这里我们需要用队列 queue 来辅助运算,如果将解法一讲解中的那个二维 dp 数组列出来的 TF 图当作一个迷宫的话,那么 BFS 的目的就是要从 (0, 0) 位置找一条都是T的路径通到 (n1, n2) 位置,这里我们还要使用 HashSet,不过此时保存到是已经遍历过的位置,队列中还是存 key 值,key 值的 encode 方法跟上面 DFS 解法的相同,初始时放个0进去。然后我们进行 while 循环,循环条件除了q不为空,还有一个是k小于 n3,因为匹配完 s3 中所有的字符就结束了。然后由于是一层层的遍历,所以要直接循环 queue 中元素个数的次数,在 for 循环中,对队首元素进行解码,得到i和j值,如果i小于 n1,说明 s1 还有剩余字符,如果 s1 当前字符等于 s3 当前字符,那么把 s1 的下一个位置 i+1 跟j一起加码算出 key 值,如果该 key 值不在于集合中,则加入集合,同时加入队列 queue 中;同理,如果j小于 n2,说明 s2 还有剩余字符,如果 s2 当前字符等于 s3 当前字符,那么把 s2 的下一个位置 j+1 跟i一起加码算出 key 值,如果该 key 值不在于集合中,则加入集合,同时加入队列 queue 中。for 循环结束后,k自增1。最后如果匹配成功的话,那么 queue 中应该只有一个 (n1, n2) 的 key 值,且k此时等于 n3,所以当 queue 为空或者k不等于 n3 的时候都要返回 false,参见代码如下:

解法四:

class Solution {public:    bool isInterleave(string s1, string s2, string s3) {        if (s1.size() + s2.size() != s3.size()) return false;        int n1 = s1.size(), n2 = s2.size(), n3 = s3.size(), k = 0;        unordered_set<int> s;        queue<int> q{{0}};        while (!q.empty() && k < n3) {            int len = q.size();            for (int t = 0; t < len; ++t) {                int i = q.front() / n3, j = q.front() % n3; q.pop();                if (i < n1 && s1[i] == s3[k]) {                    int key = (i + 1) * n3 + j;                    if (!s.count(key)) {                        s.insert(key);                        q.push(key);                    }                }                if (j < n2 && s2[j] == s3[k]) {                    int key = i * n3 + j + 1;                    if (!s.count(key)) {                        s.insert(key);                        q.push(key);                    }                }            }            ++k;        }        return !q.empty() && k == n3;    }};

关于“C++怎么解决交织相错的字符串问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网其他教程频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: C++怎么解决交织相错的字符串问题

本文链接: https://www.lsjlt.com/news/296241.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++怎么解决交织相错的字符串问题
    这篇文章主要介绍“C++怎么解决交织相错的字符串问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++怎么解决交织相错的字符串问题”文章能帮助大家解决问题。交织相错的字符串Given s...
    99+
    2023-06-19
  • C++实现LeetCode(97.交织相错的字符串)
    [LeetCode] 97.Interleaving String 交织相错的字符串 Given s1, s2, s3, find whether...
    99+
    2022-11-12
  • C语言倒置字符串问题怎么解决
    这篇文章主要介绍“C语言倒置字符串问题怎么解决”,在日常操作中,相信很多人在C语言倒置字符串问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言倒置字符串问题怎么解决”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-05
  • C++怎么解决字符串中第二大数字问题
    本篇内容主要讲解“C++怎么解决字符串中第二大数字问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++怎么解决字符串中第二大数字问题”吧!字符串中第二大的数字给你一个混合字符串 s...
    99+
    2023-07-04
  • Python字符串的字符转换、字符串劈分、字符串合并问题怎么解决
    1.字符串的字符转换1.1.字符转换的概念在前面说的的字符串替换,是将字符串中的一个子串替换成了新的子串,如果我们想对字符串中的某些字符进行转换,也就是对字符串中的单个字符进行替换,可以调用方法maketrans和translate来实现。...
    99+
    2023-05-23
    Python
  • C++中字符串处理问题的解决方法
    C++中字符串处理问题的解决方法概述:在C++编程中,字符串的处理是一个常见的问题,涉及到字符串的截取、拼接、查找、替换等操作。本文将介绍几种常用的解决方法,并提供具体的代码示例。一、字符串截取字符串截取是指从一个字符串中获取一部分子串。在...
    99+
    2023-10-22
    C++ 解决方法 字符串处理
  • 怎么解决Python字符串替换的问题
    本篇内容主要讲解“怎么解决Python字符串替换的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么解决Python字符串替换的问题”吧!项目中遇到一个字符串替换的问题。我们知道字符串替换可...
    99+
    2023-06-16
  • Golang中字符串拼接问题怎么解决
    本篇内容主要讲解“Golang中字符串拼接问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Golang中字符串拼接问题怎么解决”吧!1.概述Go的字符串是一个不可改变的数据结构,这和其...
    99+
    2023-07-06
  • MySQL字符集出错的问题怎么解决
    本篇内容主要讲解“MySQL字符集出错的问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL字符集出错的问题怎么解决”吧!  实例讲解...
    99+
    2022-10-18
  • C++中常见的字符串拼接问题解决方案
    C++中常见的字符串拼接问题解决方案在C++编程中,字符串拼接是一种常见的操作,特别是在处理文本和输出结果时。本文将介绍一些常见的字符串拼接问题,并提供相应的解决方案,同时附上代码示例以帮助读者理解。使用"+"运算符进行字符串拼接在C++中...
    99+
    2023-10-22
    字符串 解决 拼接 字符串拼接方案:
  • php截取中文字符串的问题怎么解决
    本篇内容主要讲解“php截取中文字符串的问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php截取中文字符串的问题怎么解决”吧!PHP是一款广泛使用的编程语言,在开发网站与应用程序上有...
    99+
    2023-07-05
  • C++中常见的字符串拼接问题的解决方案
    C++中常见的字符串拼接问题的解决方案在C++编程中,字符串拼接是一个常见的操作,通常用于拼接两个或多个字符串,或者将其他数据类型转换为字符串后进行拼接。在处理字符串拼接的过程中,我们需要考虑到性能和代码的简洁性。本文将介绍几种常见的字符串...
    99+
    2023-10-22
    C++ 问题解决方案 关键词:字符串拼接
  • C++中常见的字符串处理问题及解决方案
    C++中常见的字符串处理问题及解决方案引言字符串处理是在C++编程中经常遇到的问题之一。无论是从用户的输入,还是从文件中读取数据,或者是进行数据的处理和转换,字符串处理始终占据着重要的位置。本文将介绍在C++中常见的字符串处理问题,并给出相...
    99+
    2023-10-22
    C++ 解决方案 字符串处理 关键词:
  • C语言字符串处理的惊天大坑问题解决
    目录引言C 语言字符串保证 C 代码的安全性非拉丁语言的处理引言 毋庸置疑,在使用 C 字符串时必须小心,否则你就会因为各种的未定义行为而感到头疼。 最近,我一直在学习 C 语言,也...
    99+
    2023-05-20
    C语言字符串处理 C语言字符串处理问题
  • C#中常见的字符串操作问题及解决方法
    C#中常见的字符串操作问题及解决方法字符串拼接问题在C#中,我们经常需要将多个字符串拼接在一起,但是如果使用简单的加号"+"运算符,则会出现性能问题。这是因为在每次拼接字符串时,都会创建一个新的字符串对象,导致内存的频繁分配和回收。解决方法...
    99+
    2023-10-22
    解决方法 字符串操作问题
  • vbs未结束的字符串常量问题怎么解决
    在VBScript中,如果一个字符串常量没有被正确结束(例如缺少引号),那么会导致代码无法运行,因为VBScript无法识别字符串常...
    99+
    2023-06-11
    未结束的字符串常量
  • shell字符串转数组空格问题怎么解决
    在Shell中,可以使用`IFS`(Internal Field Separator)环境变量来设置分隔符,从而将字符串转换为数组。...
    99+
    2023-05-13
    shell字符串转数组 shell
  • MySQL解决Navicat设置默认字符串时的报错问题
    目录简介问题复现原因分析解决方案简介 说明 本文介绍用Navicat添加字段(字符串类型)并设置默认值时的报错问题。 问题描述 在java开发过程中,经常会遇到给已有的表添加字段的场景。 在插入新字段的时候,表里边可能已...
    99+
    2022-06-16
    MySQLNavicat设置默认字符串 MySQLNavicat默认字符串
  • mysql中replace函数替换字符串问题怎么解决
    这篇“mysql中replace函数替换字符串问题怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“mysql...
    99+
    2023-07-04
  • Redis中SDS简单动态字符串问题怎么解决
    这篇文章主要介绍“Redis中SDS简单动态字符串问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Redis中SDS简单动态字符串问题怎么解决”文章能帮助大家解决问题。一、SDS的结构&n...
    99+
    2023-07-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作