Word Wrap problem ( Space optimized solution )
Given a sequence of words, and a limit on the number of characters that can be put in one line (line width). Put line breaks in the given sequence such that the lines are printed neatly. Assume that the length of each word is smaller than the line width. When line breaks are inserted there is a possibility that extra spaces are present in each line. The extra spaces includes spaces put at the end of every line except the last one.
The problem is to minimize the following total cost.
Total cost = Sum of cost of all lines, where cost of line is = (Number of extra spaces in the line)^2.
For example, consider the following string and line width M = 15
“Geeks for Geeks presents word wrap problem”
Following is the optimized arrangement of words in 3 lines
Geeks for Geeks
presents word
wrap problem
The total extra spaces in line 1 and line 2 are 0 and 2. Space for line 3 is not considered as it is not extra space as described above. So optimal value of total cost is 0 + 2*2 = 4.
Examples:
Input format: Input will consists of array of integers where each array element represents length of each word of string. For example, for string S = "Geeks for Geeks", input array will be arr[] = {5, 3, 5}.
Output format: Output consists of a series of integers where two consecutive integers represent
starting word and ending word of each line.
Input : arr[] = {3, 2, 2, 5}
Output : 1 1 2 3 4 4
Line number 1: From word no. 1 to 1
Line number 2: From word no. 2 to 3
Line number 3: From word no. 4 to 4
Input : arr[] = {3, 2, 2}
Output : 1 1 2 2 3 3
Line number 1: From word no. 1 to 1
Line number 2: From word no. 2 to 2
Line number 3: From word no. 3 to 3
Approach: We have discussed a Dynamic Programming based solution of word wrap problem. The solution discussed used O(n^2) auxiliary space. The auxiliary space used can be reduced to O(n). The idea is to use two 1-D arrays dp[] and ans[], where dp[i] represents minimum cost of the line in which arr[i] is the first word and ans[i] represents index of last word present in line in which word arr[i] is the first word. Let k represents limit on number of characters in each line. Suppose for any line l the first word in that line is at index i in arr[]. The minimum cost of that line is stored in dp[i]. The last word in that line is at index j in arr[], where j can vary from i to n. Iterate over all values of j and keep track of number of characters added so far in line l. If number of characters are less than k then find cost of current line with these number of characters. Compare this cost with minimum cost find so far for this line in dp[i] and update dp[i] and ans[i] accordingly. Repeat above procedure for each value of i, 1 <= i <= n. The starting and ending words of each line will be at index i and index ans[i], where next value of i for line l+1 is ans[i] + 1.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
void solveWordWrap( int arr[], int n, int k)
{
int i, j;
int currlen;
int cost;
int dp[n];
int ans[n];
dp[n - 1] = 0;
ans[n - 1] = n - 1;
for (i = n - 2; i >= 0; i--) {
currlen = -1;
dp[i] = INT_MAX;
for (j = i; j < n; j++) {
currlen += (arr[j] + 1);
if (currlen > k)
break ;
if (j == n - 1)
cost = 0;
else
cost = (k - currlen) * (k - currlen) + dp[j + 1];
if (cost < dp[i]) {
dp[i] = cost;
ans[i] = j;
}
}
}
i = 0;
while (i < n) {
cout << i + 1 << " " << ans[i] + 1 << " " ;
i = ans[i] + 1;
}
}
int main()
{
int arr[] = { 3, 2, 2, 5 };
int n = sizeof (arr) / sizeof (arr[0]);
int M = 6;
solveWordWrap(arr, n, M);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static void solveWordWrap( int arr[],
int n, int k)
{
int i, j;
int currlen;
int cost;
int dp[] = new int [n];
int ans[] = new int [n];
dp[n - 1 ] = 0 ;
ans[n - 1 ] = n - 1 ;
for (i = n - 2 ; i >= 0 ; i--)
{
currlen = - 1 ;
dp[i] = Integer.MAX_VALUE;
for (j = i; j < n; j++)
{
currlen += (arr[j] + 1 );
if (currlen > k)
break ;
if (j == n - 1 )
cost = 0 ;
else
cost = (k - currlen) *
(k - currlen) +
dp[j + 1 ];
if (cost < dp[i])
{
dp[i] = cost;
ans[i] = j;
}
}
}
i = 0 ;
while (i < n)
{
System.out.print((i + 1 ) + " " +
(ans[i] + 1 ) + " " );
i = ans[i] + 1 ;
}
}
public static void main (String[] args)
{
int arr[] = { 3 , 2 , 2 , 5 };
int n = arr.length;
int M = 6 ;
solveWordWrap(arr, n, M);
}
}
|
Python 3
import sys
def solveWordWrap(arr, n, k):
dp = [ 0 ] * n
ans = [ 0 ] * n
dp[n - 1 ] = 0
ans[n - 1 ] = n - 1
for i in range (n - 2 , - 1 , - 1 ):
currlen = - 1
dp[i] = sys.maxsize
for j in range (i, n):
currlen + = (arr[j] + 1 )
if (currlen > k):
break
if (j = = n - 1 ):
cost = 0
else :
cost = ((k - currlen) *
(k - currlen) + dp[j + 1 ])
if (cost < dp[i]):
dp[i] = cost
ans[i] = j
i = 0
while (i < n):
print (i + 1 , ans[i] + 1 , end = " " )
i = ans[i] + 1
if __name__ = = "__main__" :
arr = [ 3 , 2 , 2 , 5 ]
n = len (arr)
M = 6
solveWordWrap(arr, n, M)
|
C#
using System;
class GFG
{
public static void solveWordWrap( int [] arr,
int n, int k)
{
int i, j;
int currlen;
int cost;
int [] dp = new int [n];
int [] ans = new int [n];
dp[n - 1] = 0;
ans[n - 1] = n - 1;
for (i = n - 2; i >= 0; i--)
{
currlen = -1;
dp[i] = int .MaxValue;
for (j = i; j < n; j++)
{
currlen += (arr[j] + 1);
if (currlen > k)
{
break ;
}
if (j == n - 1)
{
cost = 0;
}
else
{
cost = (k - currlen) *
(k - currlen) + dp[j + 1];
}
if (cost < dp[i])
{
dp[i] = cost;
ans[i] = j;
}
}
}
i = 0;
while (i < n)
{
Console.Write((i + 1) + " " +
(ans[i] + 1) + " " );
i = ans[i] + 1;
}
}
public static void Main( string [] args)
{
int [] arr = new int [] {3, 2, 2, 5};
int n = arr.Length;
int M = 6;
solveWordWrap(arr, n, M);
}
}
|
PHP
<?php
function solveWordWrap( $arr , $n , $k )
{
$currlen ;
$cost ;
$dp = array ();
$ans = array ();
$dp [ $n - 1] = 0;
$ans [ $n - 1] = $n - 1;
for ( $i = $n - 2; $i >= 0; $i --)
{
$currlen = -1;
$dp [ $i ] = PHP_INT_MAX;
for ( $j = $i ; $j < $n ; $j ++)
{
$currlen += ( $arr [ $j ] + 1);
if ( $currlen > $k )
break ;
if ( $j == $n - 1)
$cost = 0;
else
$cost = ( $k - $currlen ) *
( $k - $currlen ) + $dp [ $j + 1];
if ( $cost < $dp [ $i ])
{
$dp [ $i ] = $cost ;
$ans [ $i ] = $j ;
}
}
}
$i = 0;
while ( $i < $n )
{
echo ( $i + 1) . " " .
( $ans [ $i ] + 1) . " " ;
$i = $ans [ $i ] + 1;
}
}
$arr = array (3, 2, 2, 5);
$n = sizeof( $arr );
$M = 6;
solveWordWrap( $arr , $n , $M );
?>
|
Javascript
<script>
function solveWordWrap(arr, n, k)
{
var i, j;
var currlen;
var cost;
var dp = Array(n);
var ans = Array(n);
dp[n - 1] = 0;
ans[n - 1] = n - 1;
for (i = n - 2; i >= 0; i--)
{
currlen = -1;
dp[i] = 1000000000;
for (j = i; j < n; j++)
{
currlen += (arr[j] + 1);
if (currlen > k)
break ;
if (j == n - 1)
cost = 0;
else
cost = (k - currlen) * (k - currlen) + dp[j + 1];
if (cost < dp[i]) {
dp[i] = cost;
ans[i] = j;
}
}
}
i = 0;
while (i < n)
{
document.write( i + 1 + " " + (ans[i] + 1) + " " );
i = ans[i] + 1;
}
}
var arr = [ 3, 2, 2, 5 ];
var n = arr.length;
var M = 6;
solveWordWrap(arr, n, M);
</script>
|
Time Complexity: O(n^2)
Auxiliary Space: O(n), since n extra space has been taken.
Last Updated :
19 Aug, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...