Word Break - Find All Ways to Break

Last Updated : 2 Mar, 2026

Given a non-empty string s and a dictionary dict[] containing a list of non-empty words, return all possible ways to break the string in individual dictionary words.
Note: The same word in the dictionary may be reused multiple times while breaking.

Examples: 

Input: s = "likegfg" , dict[] = ["lik", "like", "egfg", "gfg"]
Output: "lik egfg", "like gfg"
Explanation: The string "likegfg" is segmented into valid dictionary words in all possible ways: "lik egfg" and "like gfg".

Input: s = "geeksforgeeks" , dict[] = ["for", "geeks"]
Output: "geeks for geeks" 
Explanation: The string "geeksforgeeks" can be broken into valid words from the dictionary in one ways.

Try It Yourself
redirect icon

[Naive Approach] Using Recursion - O((2^n) * k) Time and O(n) Space

In the recursive approach, we try to break the string starting from a given index by checking every possible substring from that position. If a substring is found in the dictionary, we recursively check whether the remaining part of the string can also be broken successfully. If we reach the end of the string, it means we were able to split the entire string into valid dictionary words, so we return true.

For implementation of the above recursive approach, please refer to Word Break Problem using Backtracking.

[Expected Approach 1] Using TopDown DP - O((n^2)*m) Time and O(n*m) Space

In the memoization approach, we solve the problem starting from a given index and store the result for that index in a map (memo). For each substring starting at start, if it exists in the dictionary, we recursively compute all valid sentence breaks from the next index (end). Before solving any index, we check if its result is already stored in memo to avoid recomputation. This ensures each starting index is processed only once, reducing overlapping subproblems.

C++
#include <iostream>
using namespace std;

vector<string> wordBreakHelper(string &s, unordered_set<string> &st, unordered_map<int, 
                               vector<string>> &memo, int start)
{

    // If the result for this index is already
    // computed, return it
    if (memo.count(start)) {
        return memo[start];
    }

    vector<string> result;

    // If start reaches the end of the string,
    // add an empty string to signify a valid sentence
    if (start == s.length())
    {
        result.push_back("");
        return result;
    }

    // Try every possible substring from the current index
    for (int end = start + 1; end <= s.length(); ++end)
    {
        string word = s.substr(start, end - start);

        // Check if the word exists in the set
        if (st.count(word))
        {
            // Recurse for the remaining string
            vector<string> subSentences = wordBreakHelper(s, st, memo, end);

            // Append the current word to each valid sub-sentence
            for (string &sub : subSentences) {
                if (sub.empty()) {
                    result.push_back(word);
                }
                else {
                    result.push_back(word + " " + sub);
                }
            }
        }
    }

    // Memoize the result for the current index
    memo[start] = result;
    return result;
}

vector<string> wordBreak(vector<string> &dict, string &s) {
    
    unordered_set<string> st(dict.begin(), dict.end());
    unordered_map<int, vector<string>> memo;
    return wordBreakHelper(s, st, memo, 0);
}

int main()
{

    string s = "likegfg";
    vector<string> dict = {"lik", "like", "egfg", "gfg" };

    vector<string> result = wordBreak(dict, s);

    for (string sentence : result) {
        cout << sentence << endl;
    }
    
    return 0;
}
Java
import java.util.*;

class GfG {
    
    static String[] wordBreakHelper(String s, HashSet<String> st,
                                    Map<Integer, String[]> memo, int start)
    {

        // If the result for this index is already computed,
        // return it
        if (memo.containsKey(start)) {
            return memo.get(start);
        }

        ArrayList<String> resultList = new ArrayList<>();

        // If start reaches the end of the string,
        // add an empty string to signify a valid sentence
        if (start == s.length()) {
            return new String[] { "" };
        }

        // Try every possible substring from the current index
        for (int end = start + 1; end <= s.length(); ++end) {
            String word = s.substring(start, end);

            // Check if the word exists in the set
            if (st.contains(word)) {
                
                // Recurse for the remaining string
                String[] subSentences = wordBreakHelper(s, st, memo, end);

                // Append the current word to each valid sub-sentence
                for (String sub : subSentences) {
                    if (sub.isEmpty()) {
                        resultList.add(word);
                    }
                    else {
                        resultList.add(word + " " + sub);
                    }
                }
            }
        }

        // Convert ArrayList to Array and Memoize the result
        // for the current index
        String[] resultArray = resultList.toArray(new String[0]);
        memo.put(start, resultArray);
        return resultArray;
    }

static String[] wordBreak(String[] dict, String s) {
    
        HashSet<String> st = new HashSet<>(Arrays.asList(dict));
        Map<Integer, String[]> memo = new HashMap<>();
        return wordBreakHelper(s, st, memo, 0);
}

    public static void main(String[] args)
    {

        String s = "likegfg";
        String[] dict = {"lik", "like", "egfg", "gfg"  };

        String[] result = wordBreak(dict, s);

        for (String sentence : result) {
            System.out.println(sentence);
        }
    }
}
Python
def wordBreakHelper(s, st, memo, start):

    # If the result for this index is already computed, return it
    if start in memo:
        return memo[start]

    result = []

    # If start reaches the end of the string,
    # add an empty string to signify a valid sentence
    if start == len(s):
        result.append("")
        return result

    # Try every possible substring from the current index
    for end in range(start + 1, len(s) + 1):
        word = s[start:end]

        # Check if the word exists in the set
        if word in st:

            # Recurse for the remaining string
            subSentences = wordBreakHelper(s, st, memo, end)

            # Append the current word to each valid sub-sentence
            for sub in subSentences:
                if sub:
                    result.append(word + " " + sub)
                else:
                    result.append(word)

    # Memoize the result for the current index
    memo[start] = result
    return result


def wordBreak(dict, s):

    st = set(dict)
    memo = {}
    return wordBreakHelper(s, st, memo, 0)


if __name__ == '__main__':

    s = "likegfg"
    dict = ["lik", "like", "egfg", "gfg" ]

    result = wordBreak(dict, s)

    for sentence in result:
        print(sentence)
C#
using System;
using System.Collections.Generic;

class GfG {

    static string[] wordBreakHelper(string s, HashSet<string> st,
                                    Dictionary<int, string[]> memo, int start)
    {

        // If the result for this index is already
        // computed, return it
        if (memo.ContainsKey(start)) {
            return memo[start];
        }

        List<string> result = new List<string>();

        // If start reaches the end of the string,
        // add an empty string to signify a valid sentence
        if (start == s.Length) {
            return new string[] { "" };
        }

        // Try every possible substring from the current index
        for (int end = start + 1; end <= s.Length; ++end) {
            string word = s.Substring(start, end - start);

            // Check if the word exists in the set
            if (st.Contains(word)) {
                string[] subSentences = wordBreakHelper(s, st, memo, end);

                // Append the current word to each valid sub-sentence
                foreach(string sub in subSentences)
                {
                    if (sub.Length > 0) {
                        result.Add(word + " " + sub);
                    }
                    else {
                        result.Add(word);
                    }
                }
            }
        }

        // Memoize the result for the current index
        string[] resultArray = result.ToArray();
        memo[start] = resultArray;
        return resultArray;
    }

    static string[] wordBreak(string[] dict, string s) {
        
        HashSet<string> st = new HashSet<string>(dict);
        Dictionary<int, string[]> memo = new Dictionary<int, string[]>();
        return wordBreakHelper(s, st, memo, 0);
}

    static void Main()
    {

        string s = "likegfg";
        string[] dict = { "lik", "like", "egfg", "gfg"  };

        string[] result = wordBreak(dict, s);

        foreach(string sentence in result)
        {
            Console.WriteLine(sentence);
        }
    }
}
JavaScript
function wordBreakHelper(s, st, memo, start)
{

    // If the result for this index is already
    // computed, return it
    if (memo.has(start)) {
        return memo.get(start);
    }

    let result = [];

    // If start reaches the end of the string,
    // add an empty string to signify a valid sentence
    if (start === s.length) {
        result.push("");
        return result;
    }

    // Try every possible substring from the current index
    for (let end = start + 1; end <= s.length; ++end) {
        let word = s.substring(start, end);

        // Check if the word exists in the dictionary
        if (st.has(word)) {
            let subSentences = wordBreakHelper(s, st, memo, end);

            // Append the current word to each
            // valid sub-sentence
            for (let sub of subSentences) {
                if (sub.length > 0) {
                    result.push(word + " " + sub);
                }
                else {
                    result.push(word);
                }
            }
        }
    }

    // Memoize the result for the current index
    memo.set(start, result);
    return result;
}

function wordBreak(dict, s)
{
    let st = new Set(dict);
    let memo = new Map();
    return wordBreakHelper(s, st, memo, 0);
}

// Driver Code
let s = "likegfg";
let dict = [ "lik", "like", "egfg", "gfg" ];

let result = wordBreak(dict, s);
result.forEach((sentence) => { console.log(sentence); });

Output
lik egfg
like gfg

[Expected Approach 2] Using BottomUp DP - O((n^2)*m) Time and O(n*m) Space

In the bottom-up DP approach, we create an array dp where dp[i] stores all valid sentences that can be formed starting from index i. We process the string from right to left, and for each index i, we check every substring s[i:j]. If the substring exists in the dictionary, we combine it with all valid sentences already stored in dp[j] and add the formed sentences to dp[i].


C++
#include <iostream>
using namespace std;

vector<string> wordBreak(vector<string> &dict, string &s) {

    // Convert dictionary to a set for fast lookups
    unordered_set<string> st(dict.begin(), dict.end());

    int n = s.length();

    // dp[i] stores all valid sentences
    // starting from index i
    vector<vector<string>> dp(n + 1);

    dp[n] = {""};

    for (int i = n - 1; i >= 0; --i)
    {

        // Check substrings starting from the
        // current index
        for (int j = i + 1; j <= n; ++j)
        {
            string word = s.substr(i, j - i);

            if (st.count(word))
            {

                // Append valid sub-sentences to the current word
                for (string &sub : dp[j])
                {
                    if (sub.empty())
                    {
                        dp[i].push_back(word);
                    }
                    else
                    {
                        dp[i].push_back(word + " " + sub);
                    }
                }
            }
        }
    }

    return dp[0];
}

int main()
{

    string s = "likegfg";
    vector<string> dict = {"lik", "like", "egfg", "gfg" };

    vector<string> res = wordBreak(dict, s);

    for (string s : res)
    {
        cout << s << endl;
    }

    return 0;
}
Java
import java.util.*;

class GfG {

    static String[] wordBreak(String[] dict, String s)
    {

        HashSet<String> st = new HashSet<>(Arrays.asList(dict));
        int n = s.length();

        // dp[i] stores all valid sentences 
        // starting from index i
        List<List<String> > dp = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            dp.add(new ArrayList<>());
        }

        dp.get(n).add("");

        for (int i = n - 1; i >= 0; --i) {

            // Check substrings starting from the current index
            for (int j = i + 1; j <= n; ++j) {
                String word = s.substring(i, j);

                if (st.contains(word)) {

                    // Append valid sub-sentences to the current word
                    for (String sub : dp.get(j)) {
                        if (sub.isEmpty()) {
                            dp.get(i).add(word);
                        }
                        else {
                            dp.get(i).add(word + " " + sub);
                        }
                    }
                }
            }
        }

        return dp.get(0).toArray(new String[0]);
    }

    public static void main(String[] args)
    {

        String s = "likegfg";
        String[] dict = {"lik", "like", "egfg", "gfg" };

        String[] result = wordBreak(dict, s);

        for (String sentence : result) {
            System.out.println(sentence);
        }
    }
}
Python
def wordBreak(dict, s):

    st = set(dict)
    n = len(s)

    # dp[i] stores all valid sentences
    # starting from index i
    dp = [[] for _ in range(n + 1)]

    dp[n].append("")

    for i in range(n - 1, -1, -1):

        # Check substrings starting from the current index
        for j in range(i + 1, n + 1):
            word = s[i:j]

            # Check if the word exists in the dictionary
            if word in st:

                # Append valid sub-sentences to the current word
                for sub in dp[j]:
                    if sub:
                        dp[i].append(word + " " + sub)
                    else:
                        dp[i].append(word)

    return dp[0]


if __name__ == '__main__':

    s = "likegfg"
    dict = ["lik", "like", "egfg", "gfg" ]

    result = wordBreak(dict, s)

    for sentence in result:
        print(sentence)
C#
using System;
using System.Collections.Generic;

class GfG {
    
    static string[] wordBreak(string[] dict, string s)
    {

        HashSet<string> st = new HashSet<string>(dict);
        int n = s.Length;

        // dp[i] stores all valid sentences 
        // starting from index i
        List<string>[] dp = new List<string>[ n + 1 ];
        for (int i = 0; i <= n; i++) {
            dp[i] = new List<string>();
        }

        dp[n].Add("");

        for (int i = n - 1; i >= 0; i--) {

            // Check substrings starting from the current index
            for (int j = i + 1; j <= n; j++) {
                string word = s.Substring(i, j - i);

                if (st.Contains(word)) {

                    // Append valid sub-sentences to the  current word
                    foreach(var sub in dp[j])
                    {
                        if (sub.Length > 0) {
                            dp[i].Add(word + " " + sub);
                        }
                        else {
                            dp[i].Add(word);
                        }
                    }
                }
            }
        }

        return dp[0].ToArray();
    }

    static void Main()
    {

        string s = "likegfg";
        string[] dict = {"lik", "like", "egfg", "gfg" };

        string[] result = wordBreak(dict, s);

        foreach(string sentence in result)
        {
            Console.WriteLine(sentence);
        }
    }
}
JavaScript
function wordBreak(dict, s)
{

    // Convert dictionary array to a Set
    let st = new Set(dict);
    let n = s.length;

    // dp[i] stores all valid sentences
    // starting from index i
    let dp = Array.from({length : n + 1}, () => []);

    dp[n].push("");

    for (let i = n - 1; i >= 0; i--) {

        // Check substrings starting from the current index
        for (let j = i + 1; j <= n; j++) {
            let word = s.substring(i, j);

            if (st.has(word)) {

                // Append valid sub-sentences to the current word
                for (let sub of dp[j]) {
                    if (sub.length > 0) {
                        dp[i].push(word + " " + sub);
                    }
                    else {
                        dp[i].push(word);
                    }
                }
            }
        }
    }

    return dp[0];
}

// Driver Code
let s = "likegfg";
let dict = ["lik", "like", "egfg", "gfg" ];

let result = wordBreak(dict, s);
result.forEach((sentence) => { console.log(sentence); });

Output
lik egfg
like gfg
Comment