Leetcode 936 戳印序列

'''
倒着进行推导,如果Target的一个子串和stamp相等,那target和stamp对齐的位置就可以全部变成?
然后?可以作为下一次匹配中的通配字符,如果最后target能变成全?,那就转换成功

关键在于怎么能快速在某个位置变成?之后知道哪些target中的区间能和stamp配起来,进而产生更多的?

可以先枚举长度为len(stamp)所有的窗口,target窗口中和stamp不同的位置就是该窗口在等待变成?的位置,每个
窗口都可以统计出等待变成?的位置集合,每次迭代都把当前等待集合为空的区间全部取出来,把其中包含的位置全部
变成?, 然后枚举所有包含了这些新?位置的区间,如果有区间刚好等待变成?的位置集合为空,那这个区间就加入到
下一轮迭代要处理的区间中,直到所有位置都变成?, 迭代结束返回中间记录的状态变化路径,如果两次迭代期间没
有新位置变成?,说明状态无法 继续更新,迭代结束,返回失败

'''


from typing import List

class Solution:
    def movesToStamp(self, stamp: str, target: str) -> List[int]:
        if len(set(target) - set(stamp)) != 0:
            return []

        # 每个位置被包在哪些区间里面
        pos2ranges = {}

        n, m = len(target), len(stamp)
        release_r = []
        for i in range(0, n-m+1):
            r = [i, i + m - 1, set()]
            flag = True
            for j in range(m):
                if stamp[j] != target[i+j]:
                    flag = False
                    r[2].add(i+j)
                    if i+j not in pos2ranges:
                        pos2ranges[i+j] = []
                    pos2ranges[i + j].append(r)

            if flag:
                release_r.append(r)

        if len(release_r) == 0:
            return []

        path = []

        del_pos = set()
        while len(release_r) != 0:
            #print(del_pos)
            new_r = []
            flag = False

            for r in release_r:
                path.append(r[0])
                for i in range(r[0], r[1] + 1):
                    if i not in del_pos:
                        del_pos.add(i)
                        flag = True

                        if i in pos2ranges:
                            for wait_r in pos2ranges[i]:
                                if len(wait_r) != 0 and i in wait_r[2]:
                                    wait_r[2].remove(i)
                                    if len(wait_r[2]) == 0:
                                        new_r.append(wait_r)

                if len(del_pos) == n:
                    return path[::-1]

            if not flag:
                break

            release_r = new_r

        return []

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值