算法

活动选择问题

活动选择问题问题可表述为“设\(S[0,1…n]\)为‘活动’的序列,每个‘活动’有开始、结束时间,\(S\)已按结束时间升序排序。规定所有‘活动’独占同一个教室,求出\(S\)中的‘活动’最多能安排多少个”。上图是其中一种\(S\)的例子。 设\(L\)是一个最优活动安排序列(已排序)。任取\(L[k]\),并用其划分序列\(L_1 = L[0,…,k-1],L_2=L[k+1,…]\)。然后设\(s_1\)是“\(L[k]\)开始前结束的\(S\)中的所有活动”,\(s_2\)是“\(L[k]\)结束后开始的\(S\)中的所有活动”。可发现如果把\(s_1,s_2\)作为原问题的输入,则\(L_1,L_2\)必可分别作为最优活动安排序列,否则\(L\)本身就不是原问题的最优解了。然后任取\(L_1[k_1]\)……可以发现上述结论是递归的。然后用这个性质去找最优解,先回到原问题上,其任意最优活动安排序列都符合“空序列,包含\(S[0]\),包含\(S[1]\),包含\(S[2]\)…”中的至少一种,如果符合的是空序列,那么解就是0,否则就遍历这些元素,设每次遍历到的元素是\(x\),然后用其划分\(S\)为“\(x\)开始前结束的\(S\)中的所有活动”,“\(x\)结束后开始的\(S\)中的所有活动”这两个序列,然后分别递归的求出它们的解并计做\(c_1,c_2\),然后求出\(c=c_1+1+c_2\),即放入\(x\)后的总活动数。每次遍历都会求一次\(c\),其中最大的那个就是解。… 阅读全文

哈夫曼编码

字符编码编码指把相同信息在不同的形式间转化,例如把图片储存为像素(x,y,r,g,b),把直角坐标方程改写为极坐标方程,把26个字母用26个二进制数表示,把明文转为密码和密文等等。无论信息形式如何变化,它们依然是同样的信息。字符编码研究如何用二进制形式表示某种语言的字符,其可被分类为定长编码与变长编码。基础ASCII码是种定长编码,无论是英文逗号、空格、回车、换行甚至响铃都有自己的ASCII码。其定长策略是在所有二进制数(编码)前补0,保证每个编码都是7-Bit。强国官方编码GB18030是种变长编码,其有1/2/4字节三种长度,1字节长度的是ASCII的超集,2字节长度的是GBK的超集,4字节长度的是其他新加入的生僻的中文字符与中文符号。   前缀编码对任意字符串的任意前缀编码方案,每个字符的编码都不是其他编码的前缀。任何前缀编码方案都可用二叉树(如上图)表示,其非叶节点的左/右边表示0/1,从根节点出发可根据编码方案“生成”编码树。由于前缀码间互不为前缀,故字符不会出现在非叶节点,故叶节点必为被编码字符本身。对字符串\(S\)与其前缀编码二叉树\(T\),设\(f(c)\)为字符\(c\)的出现次数,\(d(c)\)为字符\(c\)在前缀编码二叉树的深度,编码二叉树所对应的代价为\(B(T)=\sum… 阅读全文

多模匹配问题与AC自动机

多模匹配与AC自动机 多模匹配指“给定单个目标串与多个模式串,确定所有模式串在目标串中的所有出现位置”,相比单模匹配的“单个模式串,首次出现”,多模匹配明显更抽象和复杂(我的看法是AC自动机比KMP难一些)。这里把目标串和模式串分别计为\(t\)和\(p_1,p_2…\),还是老样子先简单的找一个多模匹配的朴素算法如下。 1)从\(t\)的第1位字符开始,与模式串\(p_1\)逐位对齐比较,匹配成功则记录\(p_1\)在第1位出现1次; 2)从\(t\)的第1位字符开始,与模式串\(p_2\)逐位对齐比较,匹配成功则记录\(p_2\)在第1位出现1次; … n)从\(t\)的第2位字符开始,与模式串\(p_1\)逐位对齐比较,匹配成功则记录\(p_1\)在第2位出现1次; …… 阅读全文

编辑距离与最小编辑距离问题

编辑距离模型 给出3种编辑距离模型中对“编辑”操作的定义: 1) Levenshtein距离:允许“替换1个字符、任意位置删1个字符、任意位置插1个字符”,权重都是1; 2) LCS距离(最长公共子序列距离):允许“任意位置删1个字符、任意位置插1个字符”,权重都是1; 3) Hamming距离:允许“替换1个字符”,权重都是1(两串长度不同时其Hamming距离是无穷); 所有编辑距离模型对“距离”的定义都是“将\(s_1\)通过模型允许的操作转化为\(s_2\)所耗费的权重”,那么最小编辑距离的定义就是“将\(s_1\)通过模型允许的操作转化为\(s_2\)需要的最小权重”。可以发现“最小编辑距离”是一类定量刻画字符串“相似度”的方案,其通过“编辑复杂程度”刻画“相似度”。 另外,最小编辑距离之所以称为“距离”是因为上述3个模型所定义的最小编辑距离满足数学上距离空间(度量空间)的性质。比如设\(L(s_1,s_2)\)为\(s_1\)到\(s_2\)的最小Levenshtein距离,其满足如下度量空间性质:… 阅读全文

拟阵理论与通用贪心算法

拟阵的定义 拟阵(Matroid)一词最早于1935年被数学家Whitney使用,其是从矩阵的线性无关概念中提炼而来的,拟阵多种不同的等价定义,其基于子集系统的定义如下,第1~4定义了子集系统,拟阵是满足交换性质的子集系统: 1) 拟阵\(M\)是为二元组\((S,L)\); 2) \(S\)是有限集合; 3) \(L\)是由\(S\)的符合下述性质的子集组成的有限非空集; 4) 遗传性质:对任意\(B\in L\)与\(A\subseteq B\),都满足\(A\in L\); 5) 交换性质:对任意\(A\in L\)与\(B\in L\)。若\(|A|<|B|\),则存在\(x \in B-A\),使\(A\bigcup\{x\} \in L\); 在无向图\((V,E)\)上可定义图拟阵(Graphic Matroid),图拟阵与拟阵等价,故图拟阵也可定义拟阵:… 阅读全文

拟阵下的单位时间任务调度问题

问题描述 单位时间任务的最优调度问题的原型是操作系统在单核CPU上的调度,其需要的输入信息如下。问题的目标是找到\(S\)的一个调度(排序),可以使得超过截止时间后的总惩罚值最小。 1) \(n\)个单位时间(耗费时间为1)任务的集合\(S=\{a_1,a_2…\} \); 2) \(n\)个整数的期望的截止时间\(\{d_1,d_2…\} \),显然\(1 \leq d_i \leq n\); 3) \(n\)个非负的惩罚值\(\{w_1,w_2…\} \); 在讨论问题前,预先给出更进一步的定义与相关性质如下: 1) 提前任务:任务在某个调度的截止时间前完成,称该任务为该调度的提前任务; 2) 延迟任务:任务在某个调度的截止时间后完成,称该任务为该调度的延迟任务; 3) 提前优先调度:任意调度可在总惩罚值不变时,把所有提前任务排在延迟任务前;… 阅读全文

动态规划

动态规划 20世纪50年代初,美国数学家R.Bellman等在创立了动态规划(Dynamic Programming),用于解决多阶段决策过程的问题。所以动态规划最早是应用数学、运筹学中的概念,并非算法概念。在用动态规划策略解决问题时,解题者需要先把问题拆分成有序的多个“阶段”,这些“阶段”的“形式”通常一样。后面的“阶段”的解可以根据前面若干个不同“阶段”的解来确定,但不能被更后面的“阶段”的解所决定(这也称为无后效性)。这种关系需要被描述成通常包含递推函数的“状态转移方程”。借助状态转移方程,就能依次得到每个“阶段”的解,最终得到问题的解。可以发现,“阶段”就类似分治法中的“子问题”,“状态转移方程”就类似解决“子问题”的递归程序,所以动态规划和分治法的策略框架基本一样,也可能分治法外延更广一点。… 阅读全文

(01)背包问题

(01)背包问题 之前讨论过该问题的一种分治算法,这里讨论一种更优的DP(动态规划)算法,其沿用之前的子问题划分思路,依赖数值的递推关系。先定义函数\(F(k,V)\)为“体积\(V\)的背包与物品前\(k+1\)项子序列\([t_0…t_k]\)能取到的最大总价值”。根据在分治法的讨论,可得\(F\)的递推式\(F(k,V) = max\{ F(k-1,V-A_k)+B_k, F(k-1,V) \} \),该式也称为状态转移方程。需要注意其边界情况,\(V-A_k<0\)时说明物品本身的体积就超过背包容积,此时\(F(k,V)=F(k-1,V)\)。另一个边界情况是序号取-1时,显然有\(F(-1,V)=0\)。此时等于找到了最大总价值的递推关系,而不是解本身的递推关系。 然后是求\(F(k,V)\),这里不用分治法“自顶向下递归”的方式,而是用“自底向上迭代”的方式。先初始化二维序列\(F[x][y]\),然后从\(F[0][0]\)开始计算出每个下标对应的值,直到得出\(F[k][V]\)本身。这是DP中常用的计算方式,其相比函数递归,能避免对同一输入的多次计算,其缺点是需要建立维护数组,也会计算一部分之后用不上的值。… 阅读全文

二维(01)背包问题

二维(01)背包问题 其可描述为“设物品序列中每个物品只有1个,物品\(i\)有2个费用属性\(x_i,y_i\),有1个价值属性\(w_i\)。给定2个正整数\(U,V\),求物品组合使\(\sum x_k \leq U \)与\(\sum y_k \leq V \)时,\(\sum w_k\)最大”。形象一点来说就是背包除了体积限制,还有重量限制。 问题的状态转移方程是\(F(i,u,v) = max\{~ F(k-1,u-x_i,v-y_i)+w_i, F(k-1,u,v) ~ \} \),参考(01)背包的思路很容易找到和证明该方程。问题的一个边界是\(u-x_i<0\)或\(v-y_i<0\)取\(F(i,u,v) = F(k-1,u,v) \)。下面给出用动态规划求解出\(F(i,u,v)\)的步骤,并且不讨论如何用求出来的\(F\)得到具体解。… 阅读全文

物品分组(01)背包问题

物品分组(01)背包问题 该问题是在(01)背包问题上附加条件“所有物品一开始被划入了几个不相交的物品组,且每组只能从中取其中一个”。这里不妨规定物品组也以序列给出,而每个物品组又都是1个物品序列。这里稍微改下\(F(k,V)\)的定义为“体积\(V\)的背包与物品组前\(k+1\)项子序列能取到的最大总价值”,即\(k\)是关于物品组的。 列出状态转移方程\(F(k,V) =max\{~F(k-1,V),~max\{ F(k-1, V-A_{k,i}) + B_{k,i} | i\in [0,|A_k|-1] \}~  \} \),\(i\)是当前物品分组中的物品下标,\(A,B\)按二维数组(物品分组下标,物品下标)提供。得到方程的思路跟其他背包问题相似,这里略去讨论。要注意边界情况的处理,\(V-A_{k,i}<0\)时应直接剔除,不参与求\(max\)。这里同样略去通过\(F\)得到具体解的步骤。… 阅读全文
滚动至顶部