Разбейте текст равномерно на определенное количество строк

12

Существует линейный алгоритм времени для равномерного разбиения текста на строки максимальной ширины. Он использует SMAWK (или Knuth & Plass) и «равномерно» означает: http://en.wikipedia.org/wiki/Word_wrap#Minimum_raggedness

Существует ли алгоритм или вогнутая функция стоимости для алгоритма, описанного выше, которая бы учитывала количество строк, на которые я хотел бы разбить текст, вместо максимальной ширины строки? Также в линейное время?

Другими словами, я ищу алгоритм разрыва строки (или формирования абзаца, или переноса слов), в котором вводом является желаемое количество строк, а не желаемая ширина строки.

Просто для описания практически непригодного подхода: между каждой парой слов есть N слов и N-1 пробелов, M - желаемое количество строк (M <= N). После каждого пробела может быть не более одного (возможно, нулевого) переноса строки. Теперь алгоритм будет пытаться поместить разрывы в каждую возможную комбинацию, вычисляя «неровность» и возвращая лучшую. Как сделать это намного быстрее?

Кроме того, у такой проблемы есть имя? К какой «семье» проблем это относится? (Например, «упаковка в мусорное ведро»). Если мне не понадобится совершенно оптимальное решение, просто очень хорошее, можно ли решить его намного быстрее? (некоторая форма эвристики могла бы быть полезной, если бы для данного входа всегда было одно и то же, возможно, неоптимальное, решение).

Обновить

Чандра Чекури предложил ниже «проблему в главе Клейнберга и Тардоса о динамическом программировании». Это было хорошее чтение, но оно имеет дело с разрывом строки на основе ширины, а не количества строк. Это может быть приспособлено к этой проблеме, которую я сейчас пытаюсь выяснить. Вот хорошая ссылка на решение, они даже утверждают, что решают его за линейное время: http://web.media.mit.edu/~dlanman/courses/cs157/HW5.pdf

Кроме того, в «Руководстве по проектированию алгоритмов» Skiena есть глава «8.5. Проблема разбиения», которая, кажется, в точности соответствует теме, я все еще читаю ее. (К сожалению, из того, что я понял, это имеет сложность квадратичного времени)

Ecir Hana
источник
5
Хорошая проблема динамического программирования! Я мог бы использовать это как домашнее задание в моем классе в следующем семестре.
Джефф
3
@ Jɛ ff E, если вы хотите использовать его для решения домашней задачи, лучше закройте вопрос, прежде чем ответ будет опубликован в Интернете.
Джо
1
@Joe: как кто-то действительно заинтересован в ответе, я предпочел бы, чтобы на вопрос отвечали, а не закрывали.
Ecir Hana
2
@Joe: это не домашняя работа, я даже не изучаю CS. Что касается «уровня домашней работы», мне очень интересно, что некоторые люди не могут даже представить, как решить проблему, в то время как другие считают его «уровнем домашней работы». Тем не менее, ответ может быть удален через неделю или отправлен на мою электронную почту, например. И я был бы благодарен за не такой «полный ответ».
Ecir Hana
3
В главе Кляйнберга и Тардоса о динамическом программировании есть проблема, которая заключается в том, чтобы отформатировать таким образом, чтобы минимизировать сумму провисаний в строках.
Чандра Чекури

Ответы:

4

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

MM

Джуни Сирен
источник
Мне очень жаль, но я не думаю, что следую. Является ли «крайний вес» длиной слова? Как выглядит «график»? Является ли это просто линейным графом, где узлы - это точки останова, а ребра - длины слов? И этот «путь M-link» разбивает его так, чтобы получающиеся сегменты имели минимальную сумму ребер? Но самое главное, в самом первом предложении - я не уверен, смогу ли я вычислить шероховатость самостоятельно. Это примерно разница между самой длинной строкой и реальной строкой, поэтому мне нужно кое-что узнать о других строках, не так ли? Более подробно о последней строке см. 15-й комментарий выше.
Ecir Hana
M1N+1(i,j)ij1
@Ecir: по сути, все алгоритмы, основанные на динамическом программировании, требуют, чтобы вы могли вычислять неровности линии независимо. Если это не так, вы можете использовать что-то вроде моей второй идеи: угадать ширину линии, вычислить решение на основе этой ширины и выполнить итерацию, чтобы найти лучшие решения.
Джоуни Сирен,
Спасибо за объяснение. Пожалуйста, у меня есть еще два вопроса: при использовании опции «бинарный поиск», что я могу сделать, чтобы гарантировать количество M строк? Если я добавлю небольшой случайный эпсилон к каждой ширине линии, чтобы не было линий с одинаковой шириной, я мог бы получить большее разрешение по сравнению с размещением разрывов.
Ecir Hana
А в случае «M-link path» обе статьи упоминают, что «легко показать, что минимальный путь K-link можно вычислить за время O (nK)» - знаете ли вы, что они имеют в виду? Я не мог найти дополнительную информацию об этом. Проблема в том, что эти документы слишком сложны для моей маленькой головы, поэтому я пытаюсь найти больше информации, возможно, реализацию ...
Ecir Hana
-3

Я не знаю, помогает ли это, но ближе к концу этого комментария кто-то реализует то, что вы хотите в PHP; может быть, вы можете выяснить алгоритм.

adrianp
источник
4
В комментарии они просто обрезают оставшиеся строки после нужного количества строк. Они используют PHP wordwrap(), который, в свою очередь, использует жадный (т.е. не «равномерный») алгоритм для переноса. Даже тогда остается вопрос, как «угадать» $widthаргумент wordwrap(). Но все равно спасибо за ответ!
Ecir Hana