Divida o texto uniformemente em determinado número de linhas

12

Existe um algoritmo de tempo linear para dividir o texto uniformemente em linhas de largura máxima. Ele usa SMAWK (ou Knuth & Plass) e significa "uniformemente": http://en.wikipedia.org/wiki/Word_wrap#Minimum_raggedness

Existe um algoritmo ou uma função de custo côncavo para o algoritmo acima, que levaria em conta o número de linhas nas quais eu gostaria que o texto fosse dividido, em vez da largura máxima da linha? Também em tempo linear?

Em outras palavras, estou procurando um algoritmo de quebra de linha (ou formação de parágrafo ou quebra de linha) em que a entrada seja o número desejado de linhas, não a largura desejada.

Apenas para descrever uma abordagem praticamente inutilizável: existem N palavras e espaços N-1 entre cada par de palavras, M é o número de linhas desejado (M <= N). Após cada espaço, pode haver no máximo uma (possivelmente zero) quebra de linha. Agora, o algoritmo tentaria colocar as quebras em cada combinação possível, calculando a "irregularidade" e retornando a melhor. Como fazer isso muito mais rápido?

Além disso, esse problema tem um nome? A que "família" de problemas pertence? (Por exemplo, "embalagem de lixeira") Se eu não precisar da solução perfeitamente ideal, apenas uma muito boa, é possível resolvê-la muito mais rapidamente? (alguma forma de heurística pode ser utilizável, se para uma determinada entrada sempre houver a mesma solução, possivelmente subótima).

Atualizar

Chandra Chekuri sugeriu abaixo "um problema no capítulo sobre programação dinâmica de Kleinberg e Tardos". Foi uma boa leitura, mas lida com a quebra de linha com base na largura e não na contagem de linhas. Pode ser adaptável a esse problema, que é algo que estou tentando descobrir agora. Aqui está um bom link para a solução, eles até afirmam resolvê-la em tempo linear: http://web.media.mit.edu/~dlanman/courses/cs157/HW5.pdf

Além disso, há um capítulo "8.5 O Problema da Partição" no Manual de Projeto de Algoritmo de Skiena que parece exatamente sobre o assunto, eu ainda estou lendo, difícil. (Infelizmente, pelo que entendi, ele tem complexidade quadrática no tempo)

Ecir Hana
fonte
5
Problema de programação dinâmica agradável! Eu poderia usá-lo como lição de casa na minha turma no próximo semestre.
26412 Jeff Jeff
3
@ Jɛ ff E se você quiser usá-lo para um problema de lição de casa, é melhor fechar a pergunta antes que a resposta seja publicada na web.
31712 Joe
1
@ Joe: como alguém realmente interessado na resposta, eu preferiria que a pergunta fosse respondida, em vez de fechada.
Ecir Hana 27/02/2012
2
@ Joe: não é um dever de casa, eu nem estudo CS. Para o que é o "nível de lição de casa", acho muito interessante que algumas pessoas nem imaginem como resolver um problema, enquanto outras o consideram "nível de lição de casa". Dito isto, a resposta pode ser apagada em uma semana ou enviada para o meu e-mail, por exemplo. E ficaria agradecido por não ser tão "resposta completa" também.
21912 Ecir Hana
3
Há um problema no capítulo de Kleinberg e Tardos sobre programação dinâmica, que é formatar de forma a minimizar a soma das folgas nas linhas.
Chandra Chekuri

Respostas:

4

MO(NlogU)UN2O(logMloglogN)M=Ω(logN)

MM

Jouni Sirén
fonte
Sinto muito, mas acho que não sigo. O "peso da borda" é o comprimento de uma palavra? Como é o "gráfico"? É apenas um gráfico linear em que os nós são os pontos de interrupção e as arestas são os comprimentos das palavras? E esse "caminho do link M" o divide para que os segmentos resultantes tenham uma soma mínima de arestas? Mas o mais importante, na primeira frase - não tenho certeza se posso calcular a irregularidade independentemente. É aproximadamente a diferença entre a linha mais longa e a linha real, então eu preciso saber algo sobre as outras linhas, não? Mais ainda para a última linha, consulte o 15º comentário acima.
precisa saber é o seguinte
M1N+1(i,j)ij1
@ Ecir: Essencialmente, todos os algoritmos baseados em programação dinâmica exigem que você possa calcular a irregularidade de uma linha independentemente. Se não for esse o caso, convém usar algo como a minha segunda ideia: adivinhe uma largura de linha, calcule uma solução com base nessa largura e repita para encontrar melhores soluções.
Jouni Sirén
Obrigado pela explicação. Por favor, tenho mais duas perguntas: ao usar a opção "pesquisa binária", há algo que eu possa fazer para garantir o número M de linhas? Se eu adicionar um épsilon aleatório pequeno a cada largura de linha para não haver linhas com a mesma largura, eu poderia obter mais resolução sobre a colocação das quebras.
Ecir Hana
E no caso do "caminho do link M", ambos os artigos mencionam que "é fácil mostrar que o caminho mínimo do link K pode ser calculado no tempo O (nK)" - você sabe o que eles significam? Não consegui encontrar mais informações. O problema é que esses papéis são um pouco demasiado complicado para a minha pequena cabeça para que eu estou tentando encontrar mais informações, uma implementação talvez, ...
Ecir Hana
-3

Não sei se isso ajuda, mas no final deste comentário alguém implementa o que você deseja em PHP; talvez você possa descobrir o algoritmo.

adrianp
fonte
4
No comentário, eles apenas cortam as linhas restantes após o número desejado de linhas. Eles usam PHP wordwrap(), que por sua vez usa o algoritmo ganancioso (ou seja, não "uniformemente") para encapsular. Mesmo assim, permanece a questão de como "adivinhar" o $widthargumento de wordwrap(). Mas obrigado pela resposta, de qualquer maneira!
Ecir Hana