Розбийте текст рівномірно на певну кількість рядків


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 Проблеми з розділами", який, здається, є абсолютно тематичним, я все ще читаю його, важко. (На жаль, з того, що я зрозумів, це квадратична часова складність)


5
Приємна проблема динамічного програмування! Я можу використовувати його як домашнє завдання у своєму класі в наступному семестрі.
Jeffε

3
@ Jɛ ff E Якщо ви хочете використовувати його для вирішення домашніх завдань, краще закрийте це питання, перш ніж відповідь буде опублікована в Інтернеті.
Джо

1
@Joe: як хтось справді зацікавлений у відповіді, я вважаю за краще відповісти на питання, а не закривати.
Ecir Hana

2
@Joe: це не домашнє завдання, я навіть не вивчаю CS. Що стосується рівня домашнього завдання, мені здається, дуже цікаво, що деякі люди навіть не можуть уявити, як вирішити проблему, а інші вважають це "рівнем домашнього завдання". Однак, відповідь можна буде стерти через тиждень або надіслати, наприклад, на мій електронний лист. І я був би вдячний і за не так "повну відповідь".
Ecir Hana

3
У главі Клейнберга та Тардоса є проблема щодо динамічного програмування, яка полягає у форматуванні таким чином, щоб мінімізувати суму пробілів у рядках.
Чандра Чекурі

Відповіді:


4

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

MM


Мені дуже шкода, але я не думаю, що я слідую за цим. Чи "вага ваги" - довжина слова? Як виглядає "графік"? Це просто лінійний графік, де вузли - точки перелому, а ребра - довжини слів? І цей "шлях М-ланки" розбиває його так, щоб отримані сегменти мали мінімальну суму ребер? Але найголовніше, що в самому першому реченні - я не впевнений, чи зможу я обчислити нерівність самостійно. Приблизно це різниця між найдовшою лінією та фактичною лінією, тому мені потрібно щось знати про інші лінії, ні? Більше про останній рядок, будь ласка, дивіться 15-й коментар вище.
Ecir Hana

M1N+1(i,j)ij1

@Ecir: По суті всі алгоритми, засновані на динамічному програмуванні, вимагають, щоб ви могли самостійно обчислити нерівність рядка. Якщо це не так, ви можете використовувати щось на зразок моєї другої ідеї: відгадати ширину рядка, обчислити рішення, засноване на цій ширині, та ітератувати пошук кращих рішень.
Jouni Sirén

дякую за пояснення. Будь ласка, у мене є ще два питання: коли ви користуєтесь опцією "двійковий пошук", чи можу я щось зробити, щоб гарантувати кількість M рядків? Якщо додати невелику випадкову епсилон до кожної ширини рядка, щоб не було рядків з однаковою шириною, я міг би отримати більшу роздільну здатність щодо розміщення перерв.
Ecir Hana

Що стосується "шляху М-ланки", обидва документи зазначають, що "легко показати, що мінімальний шлях K-посилання може бути обчислений за O (nK) час" - ви, можливо, знаєте, що вони означають? Я не зміг знайти більше інформації про це. Проблема в тому, що ці документи є занадто складними для моєї маленької голови, тому я намагаюся знайти більше інформації, можливо, реалізація, ...
Ecir Hana

-3

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


4
У коментарі вони просто обрізають решту рядків після потрібної кількості рядків. Вони використовують PHP wordwrap(), який, в свою чергу, використовує жадібний (тобто не "рівномірний") алгоритм для обгортання. Вже тоді залишається питання, як "відгадати" $widthаргумент wordwrap(). Але дякую за відповідь, все одно!
Ecir Hana
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.