Skip to content

Commit 46902d4

Browse files
authored
Merge pull request #1478 from PradnyaGaitonde/PradnyaGaitonde-patch-12
Create 0139-word-break.md
2 parents fe54f05 + bf8c3e6 commit 46902d4

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
id: word-break
3+
title: Word Break(LeetCode)
4+
sidebar_label: 0139-Word Break
5+
tags:
6+
- Array
7+
- Hash Table
8+
- String
9+
- Dynamic Programming
10+
- Trie
11+
- Memoization
12+
description: Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
13+
---
14+
15+
## Problem Statement
16+
17+
Given a string `s` and a dictionary of strings `wordDict`, return `true` if `s` can be segmented into a space-separated sequence of one or more dictionary words.
18+
19+
Note that the same word in the dictionary may be reused multiple times in the segmentation.
20+
21+
### Examples
22+
23+
**Example 1:**
24+
25+
```plaintext
26+
Input: s = "leetcode", wordDict = ["leet","code"]
27+
Output: true
28+
Explanation: Return true because "leetcode" can be segmented as "leet code".
29+
```
30+
31+
**Example 2:**
32+
33+
```plaintext
34+
Input: s = "applepenapple", wordDict = ["apple","pen"]
35+
Output: true
36+
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
37+
Note that you are allowed to reuse a dictionary word.
38+
```
39+
40+
**Example 3:**
41+
42+
```plaintext
43+
Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
44+
Output: false
45+
```
46+
47+
### Constraints
48+
49+
- `1 <= s.length <= 300`
50+
- `1 <= wordDict.length <= 1000`
51+
- `1 <= wordDict[i].length <= 20`
52+
- `s` and `wordDict[i]` consist of only lowercase English letters.
53+
- All the strings of `wordDict` are unique.
54+
55+
## Solution
56+
57+
The word break problem can be efficiently solved using dynamic programming. This approach uses a boolean vector `dp[]` where `dp[i]` is set to true if a valid word (or sequence of words) ends at the `i-th` position of the string. The key optimization here is to look backwards from the current position `i` and only consider substrings if a valid word ends at the preceding position `j` where `dp[j] == true`.
58+
59+
### Approach
60+
61+
#### Algorithm
62+
63+
1. Initialize:
64+
* If the dictionary is empty, return `false` as no word can be formed.
65+
* Create a boolean vector `dp` of size `s.size() + 1` and initialize all values to `false`.
66+
* Set `dp[0] = true` because an empty string can always be segmented (base case).
67+
2. Iterate through the string:
68+
* For each position `i` from 1 to `s.size()`:
69+
* Iterate backwards from `i-1` to 0 for each position `j`:
70+
* If `dp[j]` is `true`, it means a valid word sequence ends at `j`.
71+
* Extract the substring `s[j:i]`.
72+
* If this substring is found in the dictionary, set `dp[i]` to `true` and break out of the inner loop as we found a valid word ending at `i`.
73+
3. Return Result:
74+
* The value `dp[s.size()]` will be `true` if the string `s` can be segmented into valid words from the dictionary.
75+
76+
#### Implementation
77+
78+
```C++
79+
#include <vector>
80+
#include <string>
81+
#include <unordered_set>
82+
83+
bool wordBreak(std::string s, std::unordered_set<std::string> &dict) {
84+
if(dict.size() == 0) return false;
85+
86+
std::vector<bool> dp(s.size() + 1, false);
87+
dp[0] = true;
88+
89+
for(int i = 1; i <= s.size(); i++) {
90+
for(int j = i - 1; j >= 0; j--) {
91+
if(dp[j]) {
92+
std::string word = s.substr(j, i - j);
93+
if(dict.find(word) != dict.end()) {
94+
dp[i] = true;
95+
break; // Move to the next i
96+
}
97+
}
98+
}
99+
}
100+
101+
return dp[s.size()];
102+
}
103+
```
104+
105+
### Complexity Analysis
106+
107+
- **Time complexity**: O(N^2 * M), where `N` is the length of the string `s` and `M` is the average length of the words in the dictionary.
108+
- **Space complexity**: O(N), where `N` is the length of the string `s`.
109+
110+
### Conclusion
111+
112+
The dynamic programming approach to solving the word break problem is efficient and straightforward. By using a boolean vector to keep track of valid word endings, the algorithm ensures that each position in the string is only considered once for each potential word break. This reduces redundant computations and optimizes performance, making it feasible to solve even for relatively large strings and dictionaries.

0 commit comments

Comments
 (0)