leetcode392 判断子序列

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

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

进阶:

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

致谢:

特别感谢 @pbrother 添加此问题并且创建所有测试用例。

示例 1:

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

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

1 双指针
初始化两个指针 slow和 fast,分别指向 s 和 t的初始位置。每次贪心地匹配,匹配成功则 slow 和 fast同时右移,匹配 s 的下一个位置,匹配失败则 fast 右移,slow不变,尝试用 t 的下一个字符匹配 s。最终如果 slow 移动到 s 的末尾,就说明 s是 t 的子序列。

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        slow = 0 
        fast = 0
        while (fast < len(t)) and (slow < len(s)):
            if s[slow] == t[fast]:
                slow += 1
                fast += 1 
            else:
                fast += 1 
        return slow == len(s)

还有一个后续挑战,需要检验大量的 s 是否是 t 的子序列。在上面的双指针的方法当中,从前往后去匹配字符需要大量的时间,那么这里再使用双指针的方法显然不合适。这里参考官方题解,说一下动态规划如何去快速匹配 s 是否是 t 的子序列。首先用动态规划的方法去进行预处理。

状态定义
设 dp[i][j] 表示字符串 t 中从 i 的位置开始往后匹配,字符 j 第一次出现的位置。

状态转移方程
1 如果 t 中位置 i 的字符就是 j 的话,那么 dp[i][j] = i;
2 若不是上面的情况,那么也就是说 j 出现在 i 位置之后的某个位置,此时 dp[i][j] = dp[i+1][j]

状态初始化
i 的取值范围为 [0, t_len),当 i = t_len-1 的时候,这里可能会无法进行转移,因此我们需要把dp的初始值设置成一个无效的位置len(t),这样最后在回溯的时候,如果dp的取值依然还是len(t)+1就说明没有匹配上

def issub(s, t):
    # 初始值设置为无效值,因为t里面有效的位置为[0,len(t)-1]
    dp = [[len(t)+1]*26 for _ in range(len(t))]
    for i in range(len(t)-1, -1, -1):
        for j in range(26):
            if ord(t[i]) == ord('a') + j:
                dp[i][j] = i
            elif i == len(t) - 1:
                continue
            else:
                dp[i][j] = dp[i+1][j]


    idx = 0
    # 开始遍历s,检验 s 的每个字符在 t 中的某个位置是否存在
    for k in range(len(s)):
        # 既然k还有效,说明s还没有匹配完毕,
        # 但是这个时候如果idx已经越了t的界
        # 说明整个匹配是不成功的,返回false
        if idx > len(t) - 1:
            return False
        # 如果dp显示匹配s[k]的是一个t中的无效位置,表示无法匹配字符,那么返回 False
        if dp[idx][ord(s[k])-ord('a')] == len(t) + 1:
            return False
        # 当匹配到当前字符s[k]之后,
        # 从匹配到的dp[idx][ord(s[k])-ord('a')]这个位置的下一个位置(+1)开始,
        # 查找s[k+1]是否出现在 t 中的某个位置
        else:
            idx = dp[idx][ord(s[k])-ord('a')] + 1
            print(idx-1)
    return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值