Istnieje liniowy algorytm czasowy umożliwiający równomierne dzielenie tekstu na linie o maksymalnej szerokości. Wykorzystuje SMAWK (lub Knuth & Plass), a „równomiernie” oznacza: http://en.wikipedia.org/wiki/Word_wrap#Minimum_raggedness
Czy istnieje algorytm lub wklęsła funkcja kosztu dla algorytmu, powyżej której wziąłby pod uwagę liczbę wierszy, w których chciałbym rozbić tekst, zamiast maksymalnej szerokości linii? Również w czasie liniowym?
Innymi słowy, szukam algorytmu łamania linii (lub tworzenia akapitów lub zawijania słów), w którym dane wejściowe to żądana liczba linii, a nie pożądana szerokość linii.
Wystarczy opisać praktycznie nieużyteczne podejście: między każdą parą słów jest N słów i N-1 spacji, M jest pożądaną liczbą linii (M <= N). Po każdej spacji może być najwyżej jeden (ewentualnie zero) podział wiersza. Teraz algorytm spróbuje umieścić przerwy w każdej możliwej kombinacji, obliczając „nierówność” i zwróci najlepszą. Jak to zrobić znacznie szybciej?
Czy taki problem ma też nazwę? Do jakiej „rodziny” problemów należy? (Np. „Pakowanie pojemników”) Gdybym nie potrzebował idealnie optymalnego rozwiązania, tylko bardzo dobrego, czy można go rozwiązać znacznie szybciej? (pewna forma heurystyki mogłaby być użyteczna, gdyby dla danego wkładu zawsze istniało to samo, być może nieoptymalne rozwiązanie).
Aktualizacja
Chandra Chekuri zasugerowała poniżej „problem w rozdziale Kleinberga i Tardosa dotyczącym programowania dynamicznego”. To był dobry odczyt, ale dotyczy podziału linii na podstawie szerokości, a nie liczby linii. Być może można go dostosować do tego problemu, który próbuję teraz rozwiązać. Oto dobry link do rozwiązania, twierdzą nawet, że rozwiązuje je w czasie liniowym: http://web.media.mit.edu/~dlanman/courses/cs157/HW5.pdf
Jest też rozdział „8.5 Problem z partycjami” w Podręczniku projektowania algorytmów autorstwa Skieny, który wydaje się być dokładnie na ten temat, wciąż go czytam, ciężko. (Niestety, z tego, co zrozumiałem, ma kwadratową złożoność czasu)
źródło
Odpowiedzi:
Jeśli potrafisz obliczyć nierówność linii, nie wiedząc nic o innych liniach, możesz modelować problem jako znalezienie ścieżki łącza o minimalnej masie na wykresie. Przy wklęsłych wagach całkowitych dla krawędzi istnieje algorytm, który rozwiązuje problem w czasie , gdzie jest największą bezwzględną wagą krawędzi. Inny algorytm rozwiązuje problem w czasie dla dowolnej wagi krawędzi wklęsłej, przyjmując, że . Oba algorytmy zakładają, że można obliczyć ciężar krawędzi w stałym czasie.M. O ( NlogU) U N.2)O ( logM.loglogN.√) M.= Ω ( logN.)
Możesz także użyć wyszukiwania binarnego, aby znaleźć szerokość linii, tak że SMAWK używa z nią liniiJednak w niektórych przypadkach ten algorytm nie gwarantuje rozwiązania z dokładnie liniami.M. M.
źródło
Nie wiem, czy to pomaga, ale pod koniec tego komentarza ktoś implementuje to, co chcesz w PHP; może uda ci się wymyślić algorytm.
źródło
wordwrap()
, który z kolei używa chciwego (tzn. Nie „równomiernego”) algorytmu do zawijania. Nawet wtedy pozostaje pytanie, jak „odgadnąć”$width
argumentwordwrap()
. Ale w każdym razie dzięki za odpowiedź!