Site icon Study Algorithms

[Leetcode] – Word Break Solution

In the given problem statement, we have a string s and a dictionary wordDict containing a list of words. We need to determine if s can be segmented into a space-separated sequence of dictionary words.

The tricky part of this problem is ensuring that every segment of the string matches words from the dictionary. A brute-force approach could generate all possible segmentations, but that would be highly inefficient.

Input: s = "studyalgorithms"
wordDict = ["study", "algorithms"]
Output: true
Explanation: Since "studyalgorithms" can be split into "study" and "algorithms", both of which are in the dictionary, the function should return true.
Input: s = "catsandog", 
wordDict = ["cats","dog","sand","and","cat"]
Output: false
Explanation: No possible combination of the dictionary words can be combined to get s. Full words are to be used
Fig: Possible word break can’t get the combination right

Brute Force Approach

The brute force approach involves checking all possible partitions of the string and verifying if each segment exists in the dictionary.

This approach has a time complexity of O(2^n) due to the exponential number of possible partitions, making it impractical for large inputs.

Optimized Dynamic Programming Approach

To efficiently solve this problem, dynamic programming is used. The idea is to use a boolean array dp where dp[i] indicates whether the substring s[0..i] can be segmented using words from the dictionary.

Steps:

Fig: Word Break using a dynamic programming

Code

  boolean wordBreak(String s, List<String> wordDict) {

    // Convert the dictionary to a set for O(1) lookups
    Set<String> wordSet = new HashSet<>(wordDict);

    // Find the maximum word length in the dictionary
    int maxLen = 0;
    for (String word : wordDict) {
      maxLen = Math.max(maxLen, word.length());
    }

    int n = s.length();
    // dp[i] states if the substring s[0..i] can be segmented
    boolean[] dp = new boolean[n + 1];

    // Base case: empty string is valid
    dp[0] = true;

    for (int i = 1; i <= n; i++)

      // Check prefixes of length up to maxLen
      for (int j = i - 1; j >= Math.max(0, i - maxLen); j--)
        if (dp[j] && wordSet.contains(s.substring(j, i))) {
          dp[i] = true;
          break; // No need to check further prefixes
        }

    return dp[n];
  }
Code language: Java (java)

Time Complexity: O(n * maxLen), where n is the length of s and maxLen is the length of the longest word in the dictionary. Each substring check is optimized by restricting it to maxLen.
Space Complexity: O(n), used by the dp array.

By using dynamic programming, we significantly optimize the solution compared to brute force. The use of a dictionary set for lookups and limiting substring checks improves efficiency. This approach ensures that we can determine whether a string can be segmented efficiently, even for large inputs.

Video Explanation:

Exit mobile version