所有文本处理器都需要代码将段落中的单词拆分成不大于给定宽度的行,这一过程称为换行。有多种算法来执行这个过程,从简单到复杂,它们产生各种不同程度的“美学”输出。大多数算法试图安排段落的所有行,使它们的长度大致相同,这样可以减少文本外观上可能会分散读者注意力的视觉差异。
一个简单的换行算法是贪婪算法:将尽可能多的单词放在每一行上,然后转到下一行。例如,给定文本“aaa-bb-cc-ddddd”和线宽6,输出如下所示:
------ ------aaa bb aaa抄送bb抄送ddddd ddddd------ ------
贪婪算法将使用的行数减至最少,但大多数断线算法更喜欢将“粗糙度”减至最少。一种常用的美学度量方法是将行末的松弛度减至最少;具体地说,它寻求每一行末尾的空格数的平方的最小和。左上方显示的格式在第一行末尾没有空格,第二行末尾有4个空格,第三行末尾有1个空格,总时差为0+42+ 12= 17. 平方的目的是更严厉地惩罚大量的松弛。
右上方显示了更好的格式。它在第一行末尾有3个空格,在第二行末尾有1个空格,并且在第三行末尾有一个空格,总时差为32+ 12+ 12= 11.
从算法的角度来看,这是一个可以通过动态编程在二次时间内解决的最小化问题:遍历单词列表,计算每个单词后到该点的最小空闲时间,然后添加下一个单词并重新计算。计算最小化时使用的主要数据结构是一个上三角矩阵,如下所示:
aaa bb cc ddddd-----------------------------------0 3 0 -3 -9 0 3 01 4 1 -5 1 4 12 4 -2 2 43 1 3 1----- ----- ----- ----- ----- ----- ----- -----
第一行计算为3,即放置后剩余的空间数原子吸收光谱
在一行上,0,这是放置后剩余的空格数aaa英国广播公司
在一行上,-3,这是放置后剩余的空格数aaa bb抄送
和-9,这是放置后剩余的空格数aaa英国广播公司cc ddddd
在线上;显然,第一行上的最后两个条目是不可行的,因为线宽超过了可用空间。第二行计算为4,这是放置后剩余的空间数英国广播公司
在一行上,1,表示放置后剩余的空格数bb抄送
在一行上,和-5,这是放置后剩余的空格数bb抄送ddddd
在线上;行上的最后一项不可行。同样,第三行和第四行也是如此。上面右侧显示了上三角矩阵的可行部分。
下一步是在每列中取最小可行值:3、0、1和1;如果将其平方并计算总和,则得到32+ 02+ 12+ 12=11,这是我们上面计算的成本。更有趣的是取每列中最小可行值的索引,即0、0、1和3(原子吸收光谱
列位于索引0处英国广播公司
列位于索引0处复写的副本
列位于索引1ddddd公司
列位于索引3)。然后我们使用指数最小值成对计算换行符,如下所示:第一对0,0为空;第二对0,1定义第一输出线的边界;第三对1、3定义第二输出线的边界;而隐式对3、4(4是输入的末端)定义了第三输出行的边界。
这就是算法。请注意,将其简化为代码可能会很棘手(我不止一次弄错了),因为您必须小心地保持行和列索引笔直,并且必须记住何时加减1以指向上一列或下一列或行。该算法在计算和操作上三角矩阵时明显具有二次时间和空间复杂度。
您的任务是编写一个程序,用上面描述的动态编程算法格式化段落。完成后,欢迎您阅读或运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。
页:1 2