Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 955182e

Browse files
committed
feat: add solutions to lc problem: No.0936
No.0936.Stamping The Sequence
1 parent a1fec59 commit 955182e

File tree

8 files changed

+859
-2
lines changed

8 files changed

+859
-2
lines changed

‎solution/0900-0999/0936.Stamping The Sequence/README.md‎

Lines changed: 300 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,321 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51+
**方法一:逆向思维 + 拓扑排序**
52+
53+
如果我们正向地对序列进行操作,那么处理起来会比较麻烦,因为后续的操作会把前面的操作覆盖掉。我们不妨考虑逆向地对序列进行操作,即从目标字符串 $target$ 开始,考虑将 $target$ 变成 $?????$ 的过程。
54+
55+
我们不妨记字母印章的长度为 $m,ドル目标字符串的长度为 $n$。如果我们拿着字母印章在目标字符串上操作,那么一共有 $n-m+1$ 个开始位置可以放置字母印章。我们可以枚举这 $n-m+1$ 个开始位置,利用类似拓扑排序的方法,逆向地进行操作。
56+
57+
首先,我们明确,每个开始位置都对应着一个长度为 $m$ 的窗口。
58+
59+
接下来,我们定义以下数据结构或变量,其中:
60+
61+
- 入度数组 $indeg,ドル其中 $indeg[i]$ 表示第 $i$ 个窗口中有多少位置的字符与字母印章中的字符不同,初始时,$indeg[i]=m$。若 $indeg[i]=0,ドル说明第 $i$ 个窗口中的字符都与字母印章中的字符相同,那么我们就可以在第 $i$ 个窗口中放置字母印章。
62+
- 邻接表 $g,ドル其中 $g[i]$ 表示目标字符串 $target$ 的第 $i$ 个位置上,所有与字母印章存在不同字符的窗口的集合。
63+
- 队列 $q,ドル用于存储所有入度为 0ドル$ 的窗口的编号。
64+
- 数组 $vis,ドル用于标记目标字符串 $target$ 的每个位置是否已经被覆盖。
65+
- 数组 $ans,ドル用于存储答案。
66+
67+
接下来,我们进行拓扑排序。在拓扑排序的每一步中,我们取出队首的窗口编号 $i,ドル并将 $i$ 放入答案数组 $ans$ 中。然后,我们枚举字母印章中的每个位置 $j,ドル如果第 $i$ 个窗口中的第 $j$ 个位置未被覆盖,那么我们就将其覆盖,并将 $indeg$ 数组中所有与第 $i$ 个窗口中的第 $j$ 个位置相同的窗口的入度减少 1ドル$。如果某个窗口的入度变为 0ドル,ドル那么我们就将其放入队列 $q$ 中等待下一次处理。
68+
69+
在拓扑排序结束后,如果目标字符串 $target$ 的每个位置都被覆盖,那么答案数组 $ans$ 中存储的就是我们要求的答案。否则,目标字符串 $target$ 无法被覆盖,我们就返回一个空数组。
70+
71+
时间复杂度 $O(n \times (n - m + 1)),ドル空间复杂度 $O(n \times (n - m + 1))$。其中 $n$ 和 $m$ 分别是目标字符串 $target$ 和字母印章的长度。
72+
5173
<!-- tabs:start -->
5274

5375
### **Python3**
5476

5577
<!-- 这里可写当前语言的特殊实现逻辑 -->
5678

5779
```python
58-
80+
class Solution:
81+
def movesToStamp(self, stamp: str, target: str) -> List[int]:
82+
m, n = len(stamp), len(target)
83+
indeg = [m] * (n - m + 1)
84+
q = deque()
85+
g = [[] for _ in range(n)]
86+
for i in range(n - m + 1):
87+
for j, c in enumerate(stamp):
88+
if target[i + j] == c:
89+
indeg[i] -= 1
90+
if indeg[i] == 0:
91+
q.append(i)
92+
else:
93+
g[i + j].append(i)
94+
ans = []
95+
vis = [False] * n
96+
while q:
97+
i = q.popleft()
98+
ans.append(i)
99+
for j in range(m):
100+
if not vis[i + j]:
101+
vis[i + j] = True
102+
for k in g[i + j]:
103+
indeg[k] -= 1
104+
if indeg[k] == 0:
105+
q.append(k)
106+
return ans[::-1] if all(vis) else []
59107
```
60108

61109
### **Java**
62110

63111
<!-- 这里可写当前语言的特殊实现逻辑 -->
64112

65113
```java
114+
class Solution {
115+
public int[] movesToStamp(String stamp, String target) {
116+
int m = stamp.length(), n = target.length();
117+
int[] indeg = new int[n - m + 1];
118+
Arrays.fill(indeg, m);
119+
List<Integer>[] g = new List[n];
120+
Arrays.setAll(g, i -> new ArrayList<>());
121+
Deque<Integer> q = new ArrayDeque<>();
122+
for (int i = 0; i < n - m + 1; ++i) {
123+
for (int j = 0; j < m; ++j) {
124+
if (target.charAt(i + j) == stamp.charAt(j)) {
125+
if (--indeg[i] == 0) {
126+
q.offer(i);
127+
}
128+
} else {
129+
g[i + j].add(i);
130+
}
131+
}
132+
}
133+
List<Integer> ans = new ArrayList<>();
134+
boolean[] vis = new boolean[n];
135+
while (!q.isEmpty()) {
136+
int i = q.poll();
137+
ans.add(i);
138+
for (int j = 0; j < m; ++j) {
139+
if (!vis[i + j]) {
140+
vis[i + j] = true;
141+
for (int k : g[i + j]) {
142+
if (--indeg[k] == 0) {
143+
q.offer(k);
144+
}
145+
}
146+
}
147+
}
148+
}
149+
for (int i = 0; i < n; ++i) {
150+
if (!vis[i]) {
151+
return new int[0];
152+
}
153+
}
154+
Collections.reverse(ans);
155+
return ans.stream().mapToInt(Integer::intValue).toArray();
156+
}
157+
}
158+
```
159+
160+
### **C++**
161+
162+
```cpp
163+
class Solution {
164+
public:
165+
vector<int> movesToStamp(string stamp, string target) {
166+
int m = stamp.size(), n = target.size();
167+
vector<int> indeg(n - m + 1, m);
168+
vector<int> g[n];
169+
queue<int> q;
170+
for (int i = 0; i < n - m + 1; ++i) {
171+
for (int j = 0; j < m; ++j) {
172+
if (target[i + j] == stamp[j]) {
173+
if (--indeg[i] == 0) {
174+
q.push(i);
175+
}
176+
} else {
177+
g[i + j].push_back(i);
178+
}
179+
}
180+
}
181+
vector<int> ans;
182+
vector<bool> vis(n);
183+
while (q.size()) {
184+
int i = q.front();
185+
q.pop();
186+
ans.push_back(i);
187+
for (int j = 0; j < m; ++j) {
188+
if (!vis[i + j]) {
189+
vis[i + j] = true;
190+
for (int k : g[i + j]) {
191+
if (--indeg[k] == 0) {
192+
q.push(k);
193+
}
194+
}
195+
}
196+
}
197+
}
198+
for (int i = 0; i < n; ++i) {
199+
if (!vis[i]) {
200+
return {};
201+
}
202+
}
203+
reverse(ans.begin(), ans.end());
204+
return ans;
205+
}
206+
};
207+
```
208+
209+
### **Go**
210+
211+
```go
212+
func movesToStamp(stamp string, target string) (ans []int) {
213+
m, n := len(stamp), len(target)
214+
indeg := make([]int, n-m+1)
215+
for i := range indeg {
216+
indeg[i] = m
217+
}
218+
g := make([][]int, n)
219+
q := []int{}
220+
for i := 0; i < n-m+1; i++ {
221+
for j := range stamp {
222+
if target[i+j] == stamp[j] {
223+
indeg[i]--
224+
if indeg[i] == 0 {
225+
q = append(q, i)
226+
}
227+
} else {
228+
g[i+j] = append(g[i+j], i)
229+
}
230+
}
231+
}
232+
vis := make([]bool, n)
233+
for len(q) > 0 {
234+
i := q[0]
235+
q = q[1:]
236+
ans = append(ans, i)
237+
for j := range stamp {
238+
if !vis[i+j] {
239+
vis[i+j] = true
240+
for _, k := range g[i+j] {
241+
indeg[k]--
242+
if indeg[k] == 0 {
243+
q = append(q, k)
244+
}
245+
}
246+
}
247+
}
248+
}
249+
for _, v := range vis {
250+
if !v {
251+
return []int{}
252+
}
253+
}
254+
for i, j := 0, len(ans)-1; i < j; i, j = i+1, j-1 {
255+
ans[i], ans[j] = ans[j], ans[i]
256+
}
257+
return
258+
}
259+
```
260+
261+
### **TypeScript**
262+
263+
```ts
264+
function movesToStamp(stamp: string, target: string): number[] {
265+
const m: number = stamp.length;
266+
const n: number = target.length;
267+
const indeg: number[] = Array(n - m + 1).fill(m);
268+
const g: number[][] = Array.from({ length: n }, () => []);
269+
const q: number[] = [];
270+
for (let i = 0; i < n - m + 1; ++i) {
271+
for (let j = 0; j < m; ++j) {
272+
if (target[i + j] === stamp[j]) {
273+
if (--indeg[i] === 0) {
274+
q.push(i);
275+
}
276+
} else {
277+
g[i + j].push(i);
278+
}
279+
}
280+
}
281+
282+
const ans: number[] = [];
283+
const vis: boolean[] = Array(n).fill(false);
284+
while (q.length) {
285+
const i: number = q.shift()!;
286+
ans.push(i);
287+
for (let j = 0; j < m; ++j) {
288+
if (!vis[i + j]) {
289+
vis[i + j] = true;
290+
for (const k of g[i + j]) {
291+
if (--indeg[k] === 0) {
292+
q.push(k);
293+
}
294+
}
295+
}
296+
}
297+
}
298+
if (!vis.every(v => v)) {
299+
return [];
300+
}
301+
ans.reverse();
302+
return ans;
303+
}
304+
```
66305

306+
### **Rust**
307+
308+
```rust
309+
use std::collections::VecDeque;
310+
311+
impl Solution {
312+
pub fn moves_to_stamp(stamp: String, target: String) -> Vec<i32> {
313+
let m = stamp.len();
314+
let n = target.len();
315+
316+
let mut indeg: Vec<usize> = vec![m; n - m + 1];
317+
let mut g: Vec<Vec<usize>> = vec![Vec::new(); n];
318+
let mut q: VecDeque<usize> = VecDeque::new();
319+
320+
for i in 0..n - m + 1 {
321+
for j in 0..m {
322+
if
323+
target
324+
.chars()
325+
.nth(i + j)
326+
.unwrap() == stamp.chars().nth(j).unwrap()
327+
{
328+
indeg[i] -= 1;
329+
if indeg[i] == 0 {
330+
q.push_back(i);
331+
}
332+
} else {
333+
g[i + j].push(i);
334+
}
335+
}
336+
}
337+
338+
let mut ans: Vec<i32> = Vec::new();
339+
let mut vis: Vec<bool> = vec![false; n];
340+
341+
while let Some(i) = q.pop_front() {
342+
ans.push(i as i32);
343+
344+
for j in 0..m {
345+
if !vis[i + j] {
346+
vis[i + j] = true;
347+
348+
for &k in g[i + j].iter() {
349+
indeg[k] -= 1;
350+
if indeg[k] == 0 {
351+
q.push_back(k);
352+
}
353+
}
354+
}
355+
}
356+
}
357+
358+
if vis.iter().all(|&v| v) {
359+
ans.reverse();
360+
ans
361+
} else {
362+
Vec::new()
363+
}
364+
}
365+
}
67366
```
68367

69368
### **...**

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /