Una opción sería almacenar todas las palabras válidas en inglés en un trie. Una vez que haya hecho esto, puede comenzar a caminar desde la raíz hacia abajo, siguiendo las letras de la cadena. Cada vez que encuentre un nodo que está marcado como una palabra, tiene dos opciones:
- romper la entrada en este punto, o
- seguir extendiendo la palabra.
Puede afirmar que ha encontrado una coincidencia una vez que ha dividido la entrada en un conjunto de palabras que son todas legales y no le quedan caracteres restantes. Como en cada carta tiene una opción forzada (o bien está construyendo una palabra que no es válida y debe detenerse -o bien puede seguir ampliando la palabra) o dos opciones (dividir o seguir), podría implementar esta función utilizando la recursividad exhaustiva:
PartitionWords(lettersLeft, wordSoFar, wordBreaks, trieNode):
// If you walked off the trie, this path fails.
if trieNode is null, return.
// If this trie node is a word, consider what happens if you split
// the word here.
if trieNode.isWord:
// If there is no input left, you're done and have a partition.
if lettersLeft is empty, output wordBreaks + wordSoFar and return
// Otherwise, try splitting here.
PartitinWords(lettersLeft, "", wordBreaks + wordSoFar, trie root)
// Otherwise, consume the next letter and continue:
PartitionWords(lettersLeft.substring(1), wordSoFar + lettersLeft[0],
wordBreaks, trieNode.child[lettersLeft[0])
En el peor de los casos patológicamente esto mostrará todas las particiones de la cadena, que puede t exponencialmente larga. Sin embargo, esto solo ocurre si puede particionar la cadena de muchas formas, todas comienzan con palabras válidas en inglés y es poco probable que ocurra en la práctica. Si la cadena tiene muchas particiones, podríamos pasar mucho tiempo buscándolas. Por ejemplo, considere la cadena "dotheredo". Podemos dividir este muchas maneras:
do the redo
do the red o
doth ere do
dot here do
dot he red o
dot he redo
Para evitar esto, es posible que desee establecer un límite del número de respuestas que reporta, tal vez dos o tres.
Como cortamos la recursión cuando salimos del trie, si alguna vez intentamos una división que no deje el resto de la cadena válida, lo detectaremos rápidamente.
Espero que esto ayude!
Sé que esta es una publicación anterior, pero tuve una pregunta después de leer su excelente publicación en el blog. El O (2^n) todavía me confunde con la solución general, aunque intuitivamente podría tener sentido. Intenté usar un conbinatorics para resolverlo y resolver la recurrencia (T (n) = n * T (n-1) + O (k)) pero solo puedo obtener un límite que involucre el producto de n! con la función Gamma ¿Trataste también de resolver la recurrencia para encontrar el O (2^n)? – ak3nat0n
¿Esto ayuda? https://en.wikipedia.org/wiki/Composition_%28combinatorics%29 –