Skip to content

Commit c454c14

Browse files
authored
Merge pull request #956 from VaishnaviMankala19/leetcode30
Leetcode30
2 parents c3543dc + 8a3a7b0 commit c454c14

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
---
2+
id: substring-with-concatenation-of-all-words
3+
title: Substring with Concatenation of All Words (LeetCode)
4+
sidebar_label: 0030-SubstringWithConcatenationOfAllWords
5+
description: Find the starting indices of all substrings in the given string that are the concatenation of each word in a given list exactly once and without any intervening characters.
6+
---
7+
8+
## Problem Description
9+
10+
| Problem Statement | Solution Link | LeetCode Profile |
11+
| :---------------- | :------------ | :--------------- |
12+
| [Substring with Concatenation of All Words](https://leetcode.com/problems/subtitle-with-concatenation-of-all-words/) | [Substring with Concatenation of All Words Solution on LeetCode](https://leetcode.com/problems/subtitle-with-concatenation-of-all-words/solutions/) | [vaishu_1904](https://leetcode.com/u/vaishu_1904/) |
13+
14+
## Problem Description
15+
16+
You are given a string `s` and an array of strings `words`. All the strings of `words` are of the same length.
17+
18+
Return all starting indices of substring(s) in `s` that are the concatenation of each word in `words` exactly once, in any order, and without any intervening characters.
19+
20+
You can return the answer in any order.
21+
22+
**Example:**
23+
24+
#### Example 1
25+
26+
- **Input:** `s = "barfoothefoobarman"`, `words = ["foo","bar"]`
27+
- **Output:** `[0, 9]`
28+
- **Explanation:** Substrings starting at indices 0 and 9 are "barfoo" and "foobar" respectively. The output order does not matter, returning `[9, 0]` is fine too.
29+
30+
#### Example 2
31+
32+
- **Input:** `s = "wordgoodgoodgoodbestword"`, `words = ["word","good","best","word"]`
33+
- **Output:** `[]`
34+
35+
#### Example 3
36+
37+
- **Input:** `s = "barfoofoobarthefoobarman"`, `words = ["bar","foo","the"]`
38+
- **Output:** `[6,9,12]`
39+
40+
### Constraints
41+
42+
- `1 <= s.length <= 10^4`
43+
- `s` consists of lower-case English letters.
44+
- `1 <= words.length <= 5000`
45+
- `1 <= words[i].length <= 30`
46+
- `words[i]` consists of lower-case English letters.
47+
48+
### Approach
49+
50+
To solve this problem, we need to find all starting indices of substrings in `s` that are the concatenation of all words in `words`. Here’s a step-by-step approach:
51+
52+
1. **Initialization**:
53+
- Calculate the length of each word (`word_len`), the number of words (`num_words`), and the total length of the concatenated substring (`substring_len`).
54+
55+
2. **Sliding Window**:
56+
- Use a sliding window to check every possible starting index in `s`.
57+
- For each starting index, check if the substring from that index can be formed by concatenating all words exactly once.
58+
59+
3. **Hash Map**:
60+
- Use a hash map to store the frequency of each word in `words`.
61+
- For each window, use another hash map to count the frequency of words found in the current window.
62+
63+
4. **Validation**:
64+
- Validate if the frequency of words in the current window matches the frequency of words in the given list.
65+
66+
### Solution Code
67+
68+
#### Python
69+
70+
```python
71+
class Solution:
72+
def findSubstring(self, s, words):
73+
if not s or not words:
74+
return []
75+
76+
word_len = len(words[0])
77+
num_words = len(words)
78+
substring_len = word_len * num_words
79+
word_count = collections.Counter(words)
80+
81+
result = []
82+
83+
for i in range(word_len):
84+
left = i
85+
right = i
86+
current_count = collections.Counter()
87+
while right + word_len <= len(s):
88+
word = s[right:right + word_len]
89+
right += word_len
90+
if word in word_count:
91+
current_count[word] += 1
92+
while current_count[word] > word_count[word]:
93+
current_count[s[left:left + word_len]] -= 1
94+
left += word_len
95+
if right - left == substring_len:
96+
result.append(left)
97+
else:
98+
current_count.clear()
99+
left = right
100+
return result
101+
```
102+
#### Java
103+
```java
104+
import java.util.*;
105+
106+
class Solution {
107+
public List<Integer> findSubstring(String s, String[] words) {
108+
List<Integer> result = new ArrayList<>();
109+
if (s == null || s.length() == 0 || words == null || words.length == 0)
110+
return result;
111+
112+
int wordLen = words[0].length();
113+
int numWords = words.length;
114+
int substringLen = wordLen * numWords;
115+
116+
Map<String, Integer> wordCount = new HashMap<>();
117+
for (String word : words) {
118+
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
119+
}
120+
121+
for (int i = 0; i < wordLen; i++) {
122+
int left = i, right = i;
123+
Map<String, Integer> currentCount = new HashMap<>();
124+
while (right + wordLen <= s.length()) {
125+
String word = s.substring(right, right + wordLen);
126+
right += wordLen;
127+
if (wordCount.containsKey(word)) {
128+
currentCount.put(word, currentCount.getOrDefault(word, 0) + 1);
129+
while (currentCount.get(word) > wordCount.get(word)) {
130+
String leftWord = s.substring(left, left + wordLen);
131+
currentCount.put(leftWord, currentCount.get(leftWord) - 1);
132+
left += wordLen;
133+
}
134+
if (right - left == substringLen) {
135+
result.add(left);
136+
}
137+
} else {
138+
currentCount.clear();
139+
left = right;
140+
}
141+
}
142+
}
143+
144+
return result;
145+
}
146+
}
147+
```
148+
149+
#### c++
150+
151+
```c++
152+
#include <vector>
153+
#include <string>
154+
#include <unordered_map>
155+
using namespace std;
156+
157+
class Solution {
158+
public:
159+
vector<int> findSubstring(string s, vector<string>& words) {
160+
vector<int> result;
161+
if (s.empty() || words.empty())
162+
return result;
163+
164+
int wordLen = words[0].size();
165+
int numWords = words.size();
166+
int substringLen = wordLen * numWords;
167+
168+
unordered_map<string, int> wordCount;
169+
for (const string& word : words) {
170+
wordCount[word]++;
171+
}
172+
173+
for (int i = 0; i < wordLen; ++i) {
174+
int left = i, right = i;
175+
unordered_map<string, int> currentCount;
176+
while (right + wordLen <= s.size()) {
177+
string word = s.substr(right, wordLen);
178+
right += wordLen;
179+
if (wordCount.find(word) != wordCount.end()) {
180+
currentCount[word]++;
181+
while (currentCount[word] > wordCount[word]) {
182+
string leftWord = s.substr(left, wordLen);
183+
currentCount[leftWord]--;
184+
left += wordLen;
185+
}
186+
if (right - left == substringLen) {
187+
result.push_back(left);
188+
}
189+
} else {
190+
currentCount.clear();
191+
left = right;
192+
}
193+
}
194+
}
195+
196+
return result;
197+
}
198+
};
199+
```
200+
201+
### Conclusion
202+
The solution efficiently finds all starting indices of substrings in s that are the concatenation of all words in words using a sliding window approach and hash maps. This approach ensures that the integer division truncates toward zero as required, and handles edge cases and constraints effectively.

0 commit comments

Comments
 (0)