'''
倒着进行推导,如果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 []