C#,文字排版的折行问题(Word-wrap problem)的算法与源代码

1、英文的折行问题

给定一个单词序列,以及一行中可以输入的字符数限制(线宽)。

在给定的顺序中放置换行符,以便打印整齐。

假设每个单词的长度小于线宽。

像MS word这样的文字处理程序负责放置换行符。

这个想法是要有平衡的线条。

换句话说,不是只有几行有很多额外空间,有些行有少量额外空间。

2、中文的处理

文字断行完成后,需要进行行内排版。

文档行中各个字符的宽度之和不大可能正好等于文档容器的客户区宽度。两者会有空白差。

由于中文字符和英文字符宽度不一样,对于不等宽字体,各个英文字符、数字字符等宽度还不一样。使得各个文本行的字符宽度之和是不一样的,使得各个文档行右边缘是参差不齐的。这样比较严重的影响美观。

为此需要将文档行的宽度拉长成文档容器客户区宽度,由此会额外的制造出不少空白,此时需要将这些空白比较均匀的分摊到各个字符上。此处是比较均匀的分摊,但不是完全均匀,是有一定的分布算法的。

同一行中,字符不是相对孤立的,而且从逻辑上分为一组一组的,对于汉字和标点符号,它们是各自为政,自己组成一组。对于连续的英文字母字符和阿拉伯数字,它们逻辑上是同一组的,一起构成一个完整的单词,因此同一组之间的字符之间应该是紧密连接在一起,不得拆开。[袁永福版权所有]

为此要分摊由于文字两边对齐而造成的额外空间时,首先要对文档行的字符进行分组,然后将额外的空白平均分摊到字符组上。

3 源程序

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
	public static partial class Algorithm_Gallery
	{
		public static int WordWrap_Solve(int[] nums, int k)
		{
			int[,] memo = new int[nums.Length, k + 1];
			for (int i = 0; i < memo.GetLength(0); i++)
			{
				for (int j = 0; j < memo.GetLength(1); j++)
				{
					memo[i, j] = -1;
				}
			}
			return WordWrap_Solve_UsingMemo(nums, nums.Length, k, 0, k, memo);
		}

		private static int WordWrap_Solve_Utility(int[] words, int n, int length, int wordIndex, int remLength, int[,] memo)
		{
			if (wordIndex == n - 1)
			{
				memo[wordIndex, remLength] = words[wordIndex] < remLength ? 0 : Square(remLength);
				return memo[wordIndex, remLength];
			}

			int currWord = words[wordIndex];

			if (currWord < remLength)
			{
				int sa = WordWrap_Solve_UsingMemo(words, n, length, wordIndex + 1, (remLength == length) ? (remLength - currWord) : (remLength - currWord - 1), memo);
				int sb = Square(remLength) + WordWrap_Solve_UsingMemo(words, n, length, wordIndex + 1, length - currWord, memo);
				return Math.Min(sa, sb);
			}
			else
			{
				return Square(remLength) + WordWrap_Solve_UsingMemo(words, n, length, wordIndex + 1, length - currWord, memo);
			}
		}

		private static int WordWrap_Solve_UsingMemo(int[] words, int n, int length, int wordIndex, int remLength, int[,] memo)
		{
			if (memo[wordIndex, remLength] != -1)
			{
				return memo[wordIndex, remLength];
			}

			memo[wordIndex, remLength] = WordWrap_Solve_Utility(words, n, length, wordIndex, remLength, memo);
			return memo[wordIndex, remLength];
		}

		private static int Square(int n)
		{
			return n * n;
		}


		private static List<string> solution = new List<string>();

		public static int WWP_Solution(int[] p, int n)
		{
			int k;
			if (p[n] == 1)
			{
				k = 1;
			}
			else
			{
				k = WWP_Solution(p, p[n] - 1) + 1;
			}
			solution.Add("Line number " + k + ": From word no. " + p[n] + " to " + n);
			return k;
		}

		public static void WordWrap_Solve(int[] sentence, int n, int M)
		{
			int[,] extras = new int[n + 1, n + 1];
			int[,] lc = new int[n + 1, n + 1];
			int[] c = new int[n + 1];
			int[] p = new int[n + 1];

			for (int i = 1; i <= n; i++)
			{
				extras[i, i] = M - sentence[i - 1];

				for (int j = i + 1; j <= n; j++)
				{
					extras[i, j] = extras[i, j - 1] - sentence[j - 1] - 1;
				}
			}
			for (int i = 1; i <= n; i++)
			{
				for (int j = i; j <= n; j++)
				{
					if (extras[i, j] < 0)
					{
						lc[i, j] = int.MaxValue;
					}
					else if (j == n && extras[i, j] >= 0)
					{
						lc[i, j] = 0;
					}
					else
					{
						lc[i, j] = extras[i, j] * extras[i, j];
					}
				}
			}
			c[0] = 0;
			for (int j = 1; j <= n; j++)
			{
				c[j] = int.MaxValue;
				for (int i = 1; i <= j; i++)
				{
					if (c[i - 1] != int.MaxValue && lc[i, j] != int.MaxValue && (c[i - 1] + lc[i, j] < c[j]))
					{
						c[j] = c[i - 1] + lc[i, j];
						p[j] = i;
					}
				}
			}

			solution.Clear();
			WWP_Solution(p, n);
		}
	}
}
相关推荐
子非鱼92135 分钟前
【JavaScript】LeetCode:41-45
开发语言·javascript·leetcode·链表·二叉树
“JB...One”35 分钟前
openssl-AES-128-CTR加解密结构体
linux·数据结构·算法·ssl
爱数模的小云36 分钟前
【华为杯】2024华为杯数模研赛D题 解题思路
算法·华为
好记性+烂笔头1 小时前
hot100-438. 找到字符串中所有字母异位词
算法
六点半8881 小时前
【C/C++】速通涉及string类的经典编程题
c语言·开发语言·c++·算法
@听风吟1 小时前
力扣之182.查找重复的电子邮箱
大数据·javascript·数据库·sql·leetcode
friklogff2 小时前
【C#生态园】虚拟现实与增强现实:C#开发库全面评估
c#·ar·vr
VB.Net2 小时前
EmguCV学习笔记 VB.Net 12.1 二维码解析
opencv·计算机视觉·c#·图像·vb.net·二维码·emgucv
学地理的小胖砸2 小时前
【高分系列卫星简介】
开发语言·数码相机·算法·遥感·地理信息
__AtYou__3 小时前
Golang | Leetcode Golang题解之第417题太平洋大西洋水流问题
leetcode·golang·题解