Leetcode 392 判断子序列

题目

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

示例 1:

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

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

提示:
0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/is-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

本题要我们求解一个字符串s是否是一个字符串t的子串。
我们可以很容易想到其中双指针的解法。

一、双指针
思路:

定义两个指针指向字符串s、t的头一个字符。将两个字符进行较。如果相同,两个的指针的向前进一位 ,如果不相同,将t的指针向前进一位。只到s或t的指针到头。

代码:

 int m=t.length(),n=s.length();
 int i=0,j=0;

 while(i<m && j<n){
     if(s.charAt(j)==s.charAt(i)){
         j++;
     }
         i++;
 }

 return j==n;

二、动态规划
思路

如上的代码,我们将大量的时间花在查找下一个与s中字符匹配的字符,我们可以预处理字符串t,以便于
我们可以快速的查找到下一个匹配的字符串。

具体
使用一个二维数组 Temp[i][j] 存储预处理结果,改表达式表示 在字符串t中从i开始下一个j的位置。
(j:以a为0,表示26个字母)如果从i开始第一个j出现的位置为i(j的索引值为i,看前面i、j的含义),那么

Temp[i][j]=i;否则Temp[i][j]=temp[i+1][j];这样我们得到一个递推表达式
Temp[i][j]=i t[i]=j, Temp[i][j]=Temp[i+1][j] t[i]!=j;

预处理完成后,开始检测,我们从字符串s的第一个字符开始检测,我们设定一个数用来表示当前指针在t中的字符的位置。后面在代码中解释.

代码:

    int n = s.length(), m = t.length();

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

    for (int i = m - 1; i >= 0; i--) {
        for (int j = 0; j < 26; j++) {
            if (t.charAt(i) == j + 'a')
                f[i][j] = i;
            else
                f[i][j] = f[i + 1][j];
        }
    }
    int add = 0;  //add 表示
    for (int i = 0; i < n; i++) {  // i从 0到n-1  ,将s中的字符按顺序来检测一次
        if (f[add][s.charAt(i) - 'a'] == m) {
            return false;  //代表从add开始后面没有 i(a~z :0~25)这个字母
        }
        add = f[add][s.charAt(i) - 'a'] + 1;   //temp是预处理t的,add的值表示现在比较的起始位置,可以理解成我们我们已经提前找到下一个匹配字符的位置,完成匹配后,从当前重新开始匹配。(可以理解成  s是由t抽取出来的)
    }
    return true;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值