【问题标题】:Is it possible to develop a recursive word wrap algorithm?是否可以开发递归自动换行算法?
【发布时间】:2014-07-20 16:51:46
【问题描述】:

我想开发一种递归自动换行算法,它采用指定的字符串和换行长度(一行上的最大字符数)来返回输入长度的换行输出。我不希望它分解单词。例如,长度为 20 的 This is the first paragraph that you need to input 返回为:

This is the first
paragraph that you
need to input

我已经实现了一个动态编程(自下而上)解决方案,但我想知道是否可以编写一个算法来仅使用递归(自上而下)来执行此操作?如果可以的话,我也想记住它。请不要给我任何可运行的代码......我只是想知道想法/伪代码。

【问题讨论】:

  • 带记忆的递归算法(90%的时间)动态编程。
  • 两件事:(1)您的包装要求到底是什么?最基本的包装算法根本不需要任何递归或 DP —— 只需继续在当前行添加单词,一旦超过行长,就返回一步。 (2) 从(可能是自下而上)DP 到递归很有趣——递归是你首先获得 DP 的方式!
  • 另外,正如其他评论所说,这是通过一个非常简单的贪心算法解决的,这里不需要动态规划。
  • @j_random_hacker 仍然应该有一个 if 语句来检查 read 的单词本身是否大于行长,否则你永远不会写一行,你会只需写无限数量的换行符。
  • @BenjaminGruenbaum:我想更具体地说,我想知道是否有一种自上而下的方法,而不是我实施的自下而上的方法,如果这有意义的话。

标签: algorithm recursion word-wrap memoization


【解决方案1】:

下面的伪代码应该可以工作。 (如果我犯了错误,我相信我们会得到 cmets!)

function Wrap(the_text,line_len)

if length(the_text) > line_len then
    text_bit = the first few words of the_text, keeping their length shorter than line_len
    remove text_bit from the beginning of the_text
    return text_bit + linefeed + Wrap(the_text, line_len)
else
    return the_text
end if

end function

【讨论】:

    【解决方案2】:
    import java.lang.Math;
    
    public int RCS(int[] l , int n , int m , int index) {
    
        // first base condition - if index gets beyond the array 'l' , then return 0;
        if (index > n - 1) return 0;
    
        // second base condition - if index is the last word i.e there is only one word left in the
        // array to be inserted in the line then return the cost if added in that line.
        if (index == n - 1) return (m - l[n - 1]) * (m - l[n - 1]) * (m - l[n - 1]);
    
        // make a global cost variable to be returned
        int cost = Integer.MAX_VALUE;
    
        // Here , we try to select words from the array and apply RCS on the rest of the array.
        // From index to last element , we iteratvely select first , or first two and so on.
        for (int i = index ; i < n ; i++) {
            int current_space_sum = 0 ;
            // we add the length of the selected word. We have selected words in array from index to i.
            for (int k = index ; k <= i ; k++) {
                current_space_sum = current_space_sum + l[k] ;
            }
            // Adding the space between the words choses. If 2 words are chosen , there is one space and so on
            current_space_sum = current_space_sum + i - index;
            // If the length of the chosen words is greater than the line can accept , no need of looking beyond.
            if (current_space_sum > m) break;
            // Iteratively find the minimum cost
            cost =  Math.min(cost , (m - current_space_sum) * (m - current_space_sum) * (m - current_space_sum) + RCS(l , n , m , i + 1));
        }
        return cost;
    }
    
    
    
    public static void main(String[] args) {
        WordWrap w = new WordWrap();
        int[] l = {3, 2 , 2 , 5};
        int n = l.length;
        int m = 6;
        int result = w.RCS(l , n , m , 0);
    
        System.out.println(result);
    }
    

    【讨论】:

    • 这个工作唯一的问题是当子问题 RCS(l , n , m , i + 1) 返回 cost INT_MAX 并且我们尝试将其与当前 cost 添加时可能会溢出。因此,我建议稍微修改代码,改变 if 条件。
    • 如果我们仔细观察,就会出现一个类似于矩阵链乘法问题的模式。我们正在根据给定的约束对字符串进行分区。
    【解决方案3】:

    以下代码将帮助您获得该问题的最佳成本。

    #include<bits/stdc++.h>
    using namespace std;
    
    // method to get the optimal cost
    int findOptimalCost(int *arr, int s, int e,int lineLength,map<pair<int,int>,int>dp) {
    
    if(s>=e)    // return 0 for the last line because we are not calculating the last line space
        return 0;
    
    if(dp.find({s,e}) != dp.end()) {  // return cost if we already calculate
        return dp[{s,e}];
    }
    
    int minCost = INT_MAX;
    for(int i=s;i<=e;i++) {
        int sum = 0,space=i-s;
        for(int j =s; j<=i; j++) 
            sum += arr[j];  // add the word length 
        sum += space;  // add the space for words (if 2 word then we will count 1 space ) 
        int cost;
        if(sum<=lineLength) 
            cost = (lineLength-sum)*(lineLength-sum) + findOptimalCost(arr,s+1+space,e,lineLength,dp);  // calculate the cost for perticular line and call for rest line
            if(minCost > cost) {
                minCost = cost; // update the minCost variable if the latest cost is less then the previous calculated cost
            }
        }
    return dp[{s,e}] = minCost; // store the minimum cost for particular line and return
    }
    
    int main()
    {
    //code
        int len = 4; // total word in the list
        int arr[] = {3,2,2,5};  // let us assume the length of word
        
        int lineLength = 6; // size of max line length
        
        
        map<pair<int,int>,int> dp;
        cout<<findOptimalCost(arr,0,len-1,lineLength,dp)<<endl;
        
    return 0;
    }
    

    【讨论】:

    • 感谢您抽出宝贵时间提供答案!你能:- 1)编辑你的答案,以便详细回答。 2)解释你想用这个答案实现什么以及你想说什么?有关更多信息,请参阅如何在帮助中心写出好的答案How to Answer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2010-09-08
    • 1970-01-01
    相关资源
    最近更新 更多