2021-04-02 判断子序列

题目 判断子序列

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

示例 1:
输入:s = “abc”, t = “ahbgdc”
输出:true

示例 2:
输入:s = “axc”, t = “ahbgdc”
输出:false

解1 双指针法

根据题目可以发现,只要字符串 s 按照其顺序出现在 t 中为真。
因此通过通过 i 遍历字符串s,j 遍历字符串 t ,初始值均赋值为0;
遍历 s 的过程中,如果字符和 t[ j ]字符相等,j再往后移动遍历,即可保证 s 中的字符可以按顺序出现在 t 中。
如果 s 遍历到头,t 仍未遍历结束,说明 t 中不存在或不存在顺序的 s 的子串则返回false;

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s == "") return true;
        if(t == "") return false;
        int i,j;
        i = j = 0;
        for(i = 0 ; i<t.length() ; i++)
        {
            if(t[i] == s[j])
                j++;
            if(j == s.length())
                return true;
        }
        return false;
    }
};

解2 动态规划

用二维数组dp来存储状态,其中dp[ i ][ j ]表示字符串 t 中,从第 i 个位置往后,字符 j 第一次出现的位置。则:
若t [ i ] = j ,即 t 第 i 个位置就是字符 j ,则 i 往后第一次出现 j 的位置是 i:dp [ i ][ j ] = i;
若t [ i ] != j ,则要查看i+1往后第一次出现 j 的位置:dp[ i ][ j ] = dp[ i+1 ][ j ]

代码流程:

  1. 定义dp二维数组并初始化
    其行表示字符串 t 的全部位置,并额外最后加一行,初始化为标志值,该值不能表示字符串 t 的任意位置(代码中用t.length()表示)
    其列为26个英文小写字母,存储每个字母第 i 后出现的位置。
  2. 赋值数组
    求解dp数组的值,从最后一行向前,根据前面的动态递推公式,获取数组所有值
  3. 遍历s,通过dp数组求结果
    设置一变量pos,初始化为0,表示从 dp 数组第一个位置开始,查看 s[ 0 ] 是否在 t 中 t[ 0 ] 往后第一次出现的位置,找到对应位置dp[ pos ][s[ i ] - ‘a’],赋值给pos;对于第二个字符从t[ pos ]往后开始查找第一次出现的位置…
    若 s 中某个字符再 t 中第一次出现的位置不在t的范围内,即值为之前初始化的标记值,则 s 不是 t 的子串,返回false。
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int pos,i,j;
        int ls = s.length();
        int lt = t.length();
        vector<vector<int>> dp(lt+1 , vector<int>(26));

        //1.初始化最后一行,值全部为lt
        for(i=0 ; i<26 ; i++)
        {
            dp[lt][i] = lt;
        }

        //2.赋值数组
        for(i=lt-1 ; i>=0 ; i--)
        {
            for(j=0 ; j<26 ; j++)
            {
                if(t[i] == 'a'+j)
                    dp[i][j] = i;
                else
                    dp[i][j] = dp[i+1][j];
            }
        } 

        //3.求值
        pos = 0;
        for(i=0 ; i<ls ; i++)
        {
            if(dp[pos][s[i]-'a'] != lt)
                pos = dp[pos][s[i]-'a']+1;
            else return false;
        }
        return true;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值