LeetCode392_判断子序列

LeetCode392_判断子序列

标签:#双指针 #字符串 #动态规划

Ⅰ. 题目

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

  • 进阶:
    如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

Ⅱ. 示例

· 示例 1:

输入:s = "abc", t = "ahbgdc"

输出:true

· 示例 2:

输入:s = "axc", t = "ahbgdc"

输出:false

0. 个人方法

遍历字符串 t,逐个和 s 字符串对比,如果相同就让cnt++(我的代码里写的是 position),不同就继续遍历字符串 t,如果 cnt == s.length(),那么就说明字符串 t 中有字符串 s 这个子序列

cpp 复制代码
class Solution {
public:
    bool isSubsequence(string s, string t) {
        if (t.length() < s.length())
            return false;
        if (t.length() == 0 && s.length() == 0)
            return true;
        int position = 0;
        for (int i=0; i<t.length(); ++i)
        {
            if (t[i] == s[position])
            {
                position++;
            }
            if (position == s.length())
            {
                return true;
            }
        }

        return false;
    }
};

官方题解一:双指针

大致思路与个人方法相同

cpp 复制代码
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n && j < m) {
            if (s[i] == t[j]) {
                i++;
            }
            j++;
        }
        return i == n;
    }
};

官方题解二:动态规划

(如果需要多次查询 s 是否是 t 的子序列,DP方法更高效)

考虑到前面双指针的做法,我们注意到我们有大量的时间用于在 t 中找到下一个匹配字符。

因此,我们可以考虑对 t 进行预处理,记录从当前位置起,往后每一个字符第一次出现的位置。

cpp 复制代码
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.size(), m = t.size();
        
        // DP 表:f[i][j] 表示 t 从位置 i 开始,字符 j 第一次出现的位置
        vector<vector<int>> f(m + 1, vector<int>(26, 0));
        
        // 初始化边界:如果 t 的末尾之后的位置,所有字符都不可达(设为 m)
        for (int j = 0; j < 26; j++) {
            f[m][j] = m;
        }
        
        // 填充 DP 表
        for (int i = m - 1; i >= 0; i--) {
            for (int j = 0; j < 26; j++) {
                if (t[i] == j + 'a')  // 当前字符匹配
                    f[i][j] = i;
                else                  // 否则继承 i+1 的结果
                    f[i][j] = f[i + 1][j];
            }
        }
        
        // 遍历 s,检查是否能在 t 中找到匹配的字符
        int add = 0;  // 当前在 t 中的查找起始位置
        for (int i = 0; i < n; i++) {
            if (f[add][s[i] - 'a'] == m) {  // 字符 s[i] 在 t 中不存在
                return false;
            }
            add = f[add][s[i] - 'a'] + 1;  // 跳到匹配位置的下一个位置
        }
        
        return true;  // 所有字符都匹配成功
    }
};
  • 示例1:

    • 输入:s = "abc", t = "ahbgdc"

      • 预处理 t 后,f 会记录每个字符的位置。

      • 匹配 s:

        • 'a' 在 t 的位置 0 → add = 1

        • 'b' 在 t 的位置 2 → add = 3

        • 'c' 在 t 的位置 5 → 匹配成功

    • 输出:true

  • 示例2:

    • 输入:s = "axc", t = "ahbgdc"

      • 'a' 匹配 t[0] → add = 1

      • 'x' 在 t 中不存在 → 返回 false

相关推荐
小汉堡编程3 小时前
数据结构——vector数组c++(超详细)
数据结构·c++
tan180°8 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
彭祥.9 小时前
Jetson边缘计算主板:Ubuntu 环境配置 CUDA 与 cudNN 推理环境 + OpenCV 与 C++ 进行目标分类
c++·opencv·分类
lzb_kkk10 小时前
【C++】C++四种类型转换操作符详解
开发语言·c++·windows·1024程序员节
YuTaoShao10 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
胖大和尚11 小时前
clang 编译器怎么查看在编译过程中做了哪些优化
c++·clang
钱彬 (Qian Bin)12 小时前
一文掌握Qt Quick数字图像处理项目开发(基于Qt 6.9 C++和QML,代码开源)
c++·开源·qml·qt quick·qt6.9·数字图像处理项目·美观界面
双叶83613 小时前
(C++)学生管理系统(正式版)(map数组的应用)(string应用)(引用)(文件储存的应用)(C++教学)(C++项目)
c语言·开发语言·数据结构·c++
源代码•宸13 小时前
C++高频知识点(二)
开发语言·c++·经验分享
jyan_敬言15 小时前
【C++】string类(二)相关接口介绍及其使用
android·开发语言·c++·青少年编程·visual studio