class Solution { private fun precomputeFrom( words: List, s: String, dp: Map>, start: Int, ): List { val valid = mutableListOf() (start.. end to s.substring(start..end) } .filter { (_, word) -> words.contains(word) } .forEach { (end, word) -> when { end == s.length - 1 -> valid.add(word) else -> { dp[end + 1]?.forEach { suffix -> valid.add("$word $suffix") } } } } return valid } fun wordBreak( s: String, wordDict: List, ): List { val dp = mutableMapOf>() s.indices.reversed().forEach { start -> dp[start] = precomputeFrom(wordDict, s, dp, start) } return dp.getOrDefault(0, emptyList()) } } fun main() { val s = Solution() check( s.wordBreak("catsanddog", listOf("cat", "cats", "and", "sand", "dog")).sorted() == listOf( "cats and dog", "cat sand dog", ).sorted(), ) check( s.wordBreak("pineapplepenapple", listOf("apple", "pen", "applepen", "pine", "pineapple")).sorted() == listOf( "pine apple pen apple", "pineapple pen apple", "pine applepen apple", ).sorted(), ) check( s.wordBreak("catsandog", listOf("cats", "dog", "sand", "and", "cat")) == emptyList(), ) }