Task: Word break problem


C++: #include <algorithm>
#include <iostream>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <vector>

struct string_comparator {
    using is_transparent = void;
    bool operator()(const std::string& lhs, const std::string& rhs) const {
        return lhs < rhs;
    }
    bool operator()(const std::string& lhs, const std::string_view& rhs) const {
        return lhs < rhs;
    }
    bool operator()(const std::string_view& lhs, const std::string& rhs) const {
        return lhs < rhs;
    }
};

using dictionary = std::set<std::string, string_comparator>;

template <typename iterator, typename separator>
std::string join(iterator begin, iterator end, separator sep) {
    std::string result;
    if (begin != end) {
        result += *begin++;
        for (; begin != end; ++begin) {
            result += sep;
            result += *begin;
        }
    }
    return result;
}

auto create_string(const std::string_view& s,
                   const std::vector<std::optional<size_t>>& v) {
    auto idx = s.size();
    std::vector<std::string_view> sv;
    while (v[idx].has_value()) {
        size_t prev = v[idx].value();
        sv.push_back(s.substr(prev, idx - prev));
        idx = prev;
    }
    std::reverse(sv.begin(), sv.end());
    return join(sv.begin(), sv.end(), ' ');
}

std::optional<std::string> word_break(const std::string_view& str,
                                      const dictionary& dict) {
    auto size = str.size() + 1;
    std::vector<std::optional<size_t>> possible(size);
    auto check_word = [&dict, &str](size_t i, size_t j)
            -> std::optional<size_t> {
        if (dict.find(str.substr(i, j - i)) != dict.end())
            return i;
        return std::nullopt;
    };
    for (size_t i = 1; i < size; ++i) {
        if (!possible[i].has_value())
            possible[i] = check_word(0, i);
        if (possible[i].has_value()) {
            for (size_t j = i + 1; j < size; ++j) {
                if (!possible[j].has_value())
                    possible[j] = check_word(i, j);
            }
            if (possible[str.size()].has_value())
                return create_string(str, possible);
        }
    }
    return std::nullopt;
}

int main(int argc, char** argv) {
    dictionary dict;
    dict.insert("a");
    dict.insert("bc");
    dict.insert("abc");
    dict.insert("cd");
    dict.insert("b");
    auto result = word_break("abcd", dict);
    if (result.has_value())
        std::cout << result.value() << '\n';
    return 0;
}




Java: import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class WordBreak {

    public static void main(String[] args) {
        List<String> dict = Arrays.asList("a", "aa", "b", "ab", "aab");
        for ( String testString : Arrays.asList("aab", "aa b") ) {
            List<List<String>> matches = wordBreak(testString, dict);
            System.out.printf("String = %s, Dictionary = %s.  Solutions = %d:%n", testString, dict, matches.size());
            for ( List<String> match : matches ) {
                System.out.printf(" Word Break = %s%n", match);
            }
            System.out.printf("%n");
        }
        dict = Arrays.asList("abc", "a", "ac", "b", "c", "cb", "d");
        for ( String testString : Arrays.asList("abcd", "abbc", "abcbcd", "acdbc", "abcdd") ) {
            List<List<String>> matches = wordBreak(testString, dict);
            System.out.printf("String = %s, Dictionary = %s.  Solutions = %d:%n", testString, dict, matches.size());
            for ( List<String> match : matches ) {
                System.out.printf(" Word Break = %s%n", match);
            }
            System.out.printf("%n");
        }
    }
    
    private static List<List<String>> wordBreak(String s, List<String> dictionary) {
        List<List<String>> matches = new ArrayList<>();
        Queue<Node> queue = new LinkedList<>();
        queue.add(new Node(s));
        while ( ! queue.isEmpty() ) {
            Node node = queue.remove();
            
            if ( node.val.length() == 0 ) {
                matches.add(node.parsed);
            }
            else {
                for ( String word : dictionary ) {
                    
                    if ( node.val.startsWith(word) ) {
                        String valNew = node.val.substring(word.length(), node.val.length());
                        List<String> parsedNew = new ArrayList<>();
                        parsedNew.addAll(node.parsed);
                        parsedNew.add(word);
                        queue.add(new Node(valNew, parsedNew));
                    }
                }
            }
        }
        return matches;
    }
    
    private static class Node {
        private String val;  
        private List<String> parsed;  
        public Node(String initial) {
            val = initial;
            parsed = new ArrayList<>();
        }
        public Node(String s, List<String> p) {
            val = s;
            parsed = p;
        }
    }

}