392. 判断子序列

本文探讨了如何判断一个字符串是否为另一个字符串的子序列问题,提出了两种解决方案:双指针法和动态规划法。双指针法通过比较两个字符串的对应字符来确定子序列关系;动态规划法则通过预处理目标字符串,提高搜索效率。
摘要由CSDN通过智能技术生成

392. 判断子序列

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

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

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

思路

双指针

双指针的思路很容易想到,用两个指针分别指向s和t,字符相同时都前进一步,否则t字符串的指针前进,如果到结束s的指针还没移动到结尾,证明无法匹配。

代码

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int s_index = 0, t_index = 0;
        while(s_index < s.size() && t_index < t.size()) {
            if(s[s_index] == t[t_index]) {
                s_index++;
            }
            t_index++;
        }
        return s_index == s.size();
    }
};

动态规划

思考题假定了s的数量很大,如果每次都使用双指针方法,时间都消耗在t上寻找匹配字符了,需要对t字符串进行预处理操作,令dp[i][j]表示t字符串中从位置i开始往后第一次出现字符j的位置。
当t[i]就是字符j时,dp[i][j]=i,否则字符j出现的位置在i+1往后,故dp[i][j]=dp[i+1][j]。
边界条件,dp[m][j]=m,表示从位置m往后不可能出现字符j。

代码

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.size(), m = t.size();
        vector<vector<int>> dp(m + 1, vector<int>(26, 0));

        for(int i = 0; i < 26; i++) {
            dp[m][i] = m;
        }

        for(int i = m - 1; i >= 0; i--) {
            for(int j = 0; j < 26; j++) {
                if(j == t[i] - 'a') {
                    dp[i][j] = i;
                }
                else {
                    dp[i][j] = dp[i + 1][j];
                }
            }
        }

        int odd = 0;
        for(int i = 0; i < n; i++) {
            if(dp[odd][s[i] - 'a'] == m) {
                return false;
            }
            odd = dp[odd][s[i] - 'a'] + 1;
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值