
数据结构和算法
文章平均质量分 80
ljsspace
这个作者很懒,什么都没留下…
展开
-
三维空间中在一个经过原点的平面上的正射投影矩阵
正射投影(简称投影)是常见的一种线性变换,不过通常它会改变向量的长度,因此它不是一种正交变换。本文将采用若干种方法讨论如何将一个从原点出发的向量投影到一个过原点的平面上。在开始本文之前,需要说明的是:向量虽然没有位置,但在线性空间中需要将向量默认为是从原点出发,因为平移不是一种线性变换; 在计算投影向量时,如果要在任意平面上投影,可以事先将平面平移到原点,计算完毕后再平移回去。设三维空间中过原...原创 2019-06-30 18:32:39 · 3040 阅读 · 0 评论 -
伸展树(splay tree)自顶向下的算法
伸展树(splay tree)及其操作实现作者:ljs(转载请注明出处,谢谢!)伸展树(splay tree)是一种能自我调整的二叉搜索树(BST)。虽然某一次的访问操作所花费的时间比较长,但是平摊(amortized) 之后的访问操作(例如旋转)时间能达到O(logn)的原创 2011-06-02 12:00:00 · 5046 阅读 · 0 评论 -
斐波那契堆的实现和比较(相对二项堆)
Fibonacci Heap(简称F-Heap)是一种基于二项堆的非常灵活的数据结构。它与二项堆不同的地方在于:1)root list和任何结点的child list使用双向循环链表,而且这些lists中的结点不再有先后次序(Binomial Heap中root list的根原创 2011-09-05 14:04:31 · 10946 阅读 · 0 评论 -
RMQ+1/-1算法
RMQ+1/-1问题要求数列中相邻两个元素相差+1或-1。利用这个限定条件可以使该算法复杂度总体上达到。具体做法是:1) 设数列A的大小为n,先对数列A分组,每组大小为b=1/2.logn (之所以这样分是为了将预处理复杂度从O(nlogn)降为O(n)),共分为n/b个组;原创 2011-08-04 14:07:52 · 3496 阅读 · 0 评论 -
RMQ问题的线段树解法
RMQ(Range Minimum Query)问题是计算一个输入数列A[0...n-1]从位置i到位置j之间的最小值,即RMQ[i,j]=min{A[k], k=i,i+1...j}。RMQ的解法有很多,比如Sparse Table(ST)算法(注意这个ST缩写不是指Segem原创 2011-08-02 19:09:25 · 3624 阅读 · 0 评论 -
RMQ问题的ST算法
ST(Sparse Table)算法的基本思想是,预先计算从起点A[i]开始长度为2的j次方(j=0,1...logn)的区间的最小值,然后在查询时将任何一个区间A[i..j]划分为两个预处理好的可能重叠的区间,取这两个重叠区间的最小值。在预处理阶段,从起点A[i]开始,任何原创 2011-08-02 22:49:02 · 1461 阅读 · 0 评论 -
利用后缀树求多个字符串的最长公共连续子串(Longest Common Substring)
问题:有N个字符串,计算它们公共的最长连续子串。例如,字符串集合{abcd,bcca,aabc},它们公共的最长连续子串是bc。又如{abcfd,bcabca,aabcf}的公共的最长连续子串是abc。针对本问题,可以用特殊的字符(该字符必须是N个串中没有出现的字符)将N个字符串连起来形成一个新串,然后构建这个新串的后缀树。比如对字符串集合 {abcd,bcca,aabc},可以连成新串abcd$原创 2011-06-29 17:04:00 · 4750 阅读 · 0 评论 -
构建后缀树的Ukkonen算法及其实现
Ukkonen算法(简称ukk算法)是一个online算法,它与mcc算法的一个显著区别是每次只对S的一个前缀生成隐式后缀树(implicit suffix tree),然后考虑S的下一个字符S[i+1]并将S[0...i+1]的所有后缀加入到上一个阶段中生成的隐式后缀树中,形成原创 2011-07-10 21:50:26 · 8544 阅读 · 1 评论 -
根据后缀树得出后缀数组
后缀数组(suffix array)是字符串S的所有后缀按照一定顺序(通常是字典顺序)排列后得出的数组,数组中每个元素的值等于该后缀的起始下标。要根据后缀树得出后缀数组,只需遍历所有的叶子结点(按照从左到右的顺序依次访问每个叶子结点),因为每一个叶子结点对应一个后缀,它的起始下标原创 2011-07-13 14:47:47 · 1386 阅读 · 1 评论 -
普通RMQ问题转化为LCA问题的算法
基本思想是通过对问题的转化,最终得到时间复杂度。该算法分以下两大步骤:1)将RMQ问题转化为LCA问题:先构建输入数列A的笛卡尔树,构建笛卡尔树的复杂度为O(n)。2)将LCA问题转化为RMQ+1/-1问题:通过对笛卡尔树的DFS遍历得到欧拉路径(Euler To原创 2011-08-06 00:57:41 · 1830 阅读 · 0 评论 -
树状数组(Binary Indexed Tree)
树状数组(BIT - Binary Indexed Tree)是一个用数组表示的树型数据结构,最早用于频次累计表中。树状数组中每个元素维护一个频次表A的特定部分区段的累加和。假设输入动态序列为A,A中元素值可以被修改,如果使用直接蛮力法来查询一个区间i..j的累加和,复杂度为O(原创 2011-08-09 00:37:01 · 4360 阅读 · 1 评论 -
RMQ问题的Fischer-Heun算法(直接方法)
在普通RMQ问题的算法中,由于需要构造Cartesian Tree和得到Euler tour,两个2*n-1大小的数组E和L使得空间消耗增加O(4*n)。本文介绍的Fischer-Heun算法绕过构建Cartesian Tree的步骤,也不需要将普通RMQ转化为RMQ+1/-1问原创 2011-08-07 12:15:54 · 2850 阅读 · 1 评论 -
由1-7的随机整数函数构造1-10随机整数函数
题目:已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。分析:要保证rand10()在整数1-10的均匀分布,可以构造一个1-10*n的均匀分布的随机整数区间(n为任何正整数)。假设x是这个1-10原创 2011-09-25 23:18:16 · 15537 阅读 · 17 评论 -
Binomial Heap(English Version)
Just like leftist or skew heaps, a binomial heap is also a mergeable heap data structure. But unlike those 'lopsided' heaps that are compose原创 2011-08-29 14:39:22 · 7051 阅读 · 0 评论 -
斜堆(Skew Heap)
斜堆(Skew Heap)基于左倾堆的概念,也是一个用于快速合并的堆结构,但它可自我调整(self-adjusting),每一个merge操作的平摊成本仍为O(logN),其中N为结点数,而且和左倾堆相比,每个结点没有npl属性,从而节省了空间。斜堆并不能保证左倾,但是每一个合并原创 2011-08-25 00:01:15 · 17934 阅读 · 3 评论 -
LCA问题的在线算法(很经典的一个算法)
Tarjan算法解决LCA查询要求事先知道全部查询提问,如果LCA要求即时询问即时回答,就需要用到下面介绍的在线算法。在线算法需要对任意树进行预处理,设输入树的结点个数为n,该算法的预处理时间和空间复杂度都是O(n),查询复杂度为O(1)。本算法的基本思想是将对一棵树T做原创 2011-08-24 00:34:13 · 19930 阅读 · 1 评论 -
左倾堆(一种可高效合并的优先队列)
左倾堆(Leftist Heap)是一个便于merge操作的数据结构,通过左倾树(Leftist Tree)实现。左倾树是一种特殊的二叉树,树中结点除了满足普通二叉堆的key大小规定外,还要求每一个结点X的左子树的Null Path Length(NPL)值不小于右子树的NPL值原创 2011-08-21 00:17:05 · 10423 阅读 · 0 评论 -
LCA的Tarjan离线算法
LCA的Tarjan离线(offline)算法中,通过后序DFS遍历多叉树(结点数为n),利用并查集算法(disjoint sets‘ union-find operations),可以在线性时间O(n+|P|)内找到事先给定(即offline的含义)的|P|个成对结点的LCA。原创 2011-08-16 11:55:55 · 3167 阅读 · 0 评论 -
RMQ问题的树状数组解法
树状数组中每个元素覆盖了不同长度的子区间,类似于稀疏表(ST)算法的思想,每一个数组元素存储了输入数列A在该区间的最小值下标。注意:这里树状数组不是用来存储区间累加值,而是区间的最小值下标。在预处理阶段,采用类似于累加和中的update做法,每一个元素A[i]需要处理树状数组T中原创 2011-08-10 00:13:43 · 3535 阅读 · 0 评论 -
配对堆(Pairing Heap)
配对堆(Pairing Heap)是一个简单实用的min-heap结构(当然也可以做成max-heap)。它是一颗多路树(multiway tree),类似于Leftist Heap和Skew Heap,但是与Binomial Tree和Fibonacci Heap不一样。它的基原创 2011-09-06 01:04:02 · 20156 阅读 · 0 评论 -
使用倍增算法(Prefix Doubling)构造后缀数组
如果采用对每个后缀排序的方法来生成后缀数组,即使采用快速排序,由于每次比较的对象是字符串(设输入字符串的长度为n),因此每一个比较操作的复杂度不再是常数,而是O(n),快速排序本身的平均情况下时间复杂度为O(nlgn),因此总的时间复杂度是O(n^2lgn),如果考虑到采用快速排原创 2011-07-18 00:17:34 · 5022 阅读 · 0 评论 -
使用增强型后缀数组(ESA)的文本匹配算法
设模式串的长度为m,文本的长度为n,使用后缀数组做文本匹配,如果只用后缀表suftab和折半查找算法的复杂度为O(m*logn); 如果使用最长公共前缀表lcptab和折半查找算法,复杂度可以降至O(m+logn);使用增强型后缀数组(ESA)表childtab,复杂度为O(m)原创 2011-07-28 00:48:38 · 2179 阅读 · 2 评论 -
计算后缀数组的LCP(Longest Common Prefix)
所谓LCP(Longest Common Prefix)是指后缀数组中相邻两个后缀的最长公共前缀的长度。在后缀数组的应用中,LCP是很重要的信息。设后缀数组为SA, 用LCP(i)定义为第SA[i]个后缀和第SA[i-1]个后缀之间的最长公共前缀长度。由于输入文本T的第p个后缀和原创 2011-07-20 00:21:08 · 11568 阅读 · 0 评论 -
静态链表插入排序(List Insertion Sort)算法
静态链表插入排序(List Insertion Sort)算法是直接插入排序的一个变种。它的改进目的是减少在直接插入排序中的移动次数,因此在原输入数据的基础上附加一个静态链表(为了减少空间的消耗,静态链表实际上就是用等长的下标数组来模拟的,而不需要建立一个等长的动态链结构)。设输原创 2011-07-20 14:22:55 · 5347 阅读 · 0 评论 -
根据后缀树LCA计算后缀数组及其LCP
本文继续“根据后缀树得出后缀数组“的讨论,进一步探讨从后缀树计算后缀数组的LCP。后缀数组的LCP(Longest Common Prefix)问题等价于后缀树的最小公共祖先LCA(Least Common Ancestor)问题。下面的方法将采用“根据后缀树得出后缀数组”一文中原创 2011-07-21 22:45:42 · 3041 阅读 · 0 评论 -
KMP文本匹配算法
KMP算法作者:ljs2011-06-20(转载请注明出处,谢谢!)KMP(Knuth–Morris–Pratt)算法的发明时间几乎跟BM(Boyer-Moore)算法在同一时期,即上世纪70年代末(巧合的是随着互联网的发展对文本处理提出了更高的要求,从而最近几年字符处理又成了热门话题),二者在最坏情况下的时间复杂度都是O(n)。它与BM算法的主要区别是:1)在每次匹配中都是从左到右匹配,BM算法原创 2011-06-20 19:10:00 · 5860 阅读 · 0 评论 -
构造后缀数组的DC3算法实现
DC3算法(Difference Cover mod 3)是J. Kärkkäinen和P. Sanders在2003年发表的论文 "Simple Linear Work Suffix Array Construction"中描述的线性时间内构造后缀数组的算法。相对Prefix原创 2011-07-19 15:10:13 · 5181 阅读 · 0 评论 -
AC解 - Phone List(HDOJ#1671)前缀树的一个应用
原题:http://acm.hdu.edu.cn/showproblem.php?pid=1671Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Problem DescriptionGiven a list of phone numbers, determ原创 2011-06-28 22:24:00 · 1842 阅读 · 0 评论 -
Patricia前缀树(Patricia Trie)及其基本操作
Patricia前缀树(Patricia Trie)及其基本操作Trie是一种字典树,用于存储文本字符,并利用了单词之间共享前缀的特点,所以叫做前缀树。不像平衡BST,Trie的高度只与最长的文本串的长度s有关系,而与单词的数量n无关。Trie的节点分两种:内部结点和叶子结点,内部结点用来存储单词key的成分字母,如果设字母表大小为d,那么每个内部结点最多有d个孩子,叶子结点存储该单词作为原创 2011-06-27 23:18:00 · 16722 阅读 · 0 评论 -
AC解 - 统计带某个前缀的单词数量
原题:http://acm.hdu.edu.cn/showproblem.php?pid=1251 Problem DescriptionIgnatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input输入数据的第一部分是一张单词表,每行一个单词,原创 2011-06-27 19:01:00 · 2393 阅读 · 0 评论 -
求字符串中不含重复字符的最长子串的长度
原帖:http://topic.youkuaiyun.com/u/20100930/02/5064ef5a-b2f4-44b9-8a16-ce2bf83323c0.html?84726题目:求字符串最长不含重复字符的子串长度,如abcbec,就返回3.分析:利用动态规划(DP)原理,设字符串原创 2011-07-09 00:15:04 · 3405 阅读 · 0 评论 -
快速生成后缀树的McCreight算法及其实现
快速生成后缀树的McCreight算法及其实现作者: ljs2011-07-03(版权所有,转载请注明)McCreight算法(简称mcc算法)是基于蛮力法,即已知输入文本串T的内容(注:Ukkonen算法是online的,所以不要求事先知道T的全部内容),逐原创 2011-07-03 14:59:20 · 3837 阅读 · 0 评论 -
后缀树(Suffix Tree)的文本匹配算法
后缀树(Suffix Tree)是一种特殊的Trie,它的用途非常广泛,其中一个主要的应用是作文本匹配,也像KMP等算法一样,它也是空间换时间的一个典范。利用 Suffix Tree做文本匹配与其他的模式匹配算法比如KMP和Boyer-Moore算法的主要区别是,后缀树文本匹配算法是对文本T做预处理,而KMP算法是对模式串P做预处理。因此后缀树常用于文本静态,而模式串动态的场合;而KMP等算法常用原创 2011-06-27 23:55:00 · 6856 阅读 · 3 评论 -
压缩存储后缀数组的childtab
相比后缀树,后缀数组的优势是存储空间小,相关算法效率高。但是若存放childtab还是使用up,down和nextLIndex三个属性,这显然不符合后缀数组节省空间的"第一原则"。幸运的是,可以压缩存储childtab,将三个属性up,down和nextLIndex变成一个一维数原创 2011-07-26 13:55:48 · 1215 阅读 · 0 评论 -
后缀数组的自底向上(bottom-up)遍历算法
后缀数组自底向上遍历等价于后缀树的自底向上遍历。由于后缀数组不是树型结构,在遍历时除了SA本身之外还需要额外的信息,这时Suffix Array就是一个增强的后缀数组(Enhanced Suffix Array)了。该算法使用后缀数组的一个增强信息---LCP表,并通过堆栈模拟自原创 2011-07-23 23:53:10 · 2773 阅读 · 0 评论 -
后缀树的自顶向下(top-down)遍历
与后缀数组的top-down遍历相比,后缀树的自顶向下遍历相对直接一些。下面的实现中首先确定每一个内部结点的左右后缀边界下标(prepare方法),然后先序遍历所有内部结点。实现:import java.util.ArrayList;import java.util.Linke原创 2011-07-25 19:36:39 · 1668 阅读 · 0 评论 -
后缀数组的自顶向下(top-down)遍历算法
类似于"后缀数组的自底向上(bottom-up)遍历算法",也可以对Enhanced Suffix Array执行自顶向下(top-down)遍历。这里通过增强信息--lcptable和childtab--来自顶向下遍历后缀数组。每一个后缀的childtab元素包含up,down原创 2011-07-25 19:30:27 · 1803 阅读 · 0 评论 -
后缀树的自底向上(bottom-up)遍历算法
与后缀数组的自底向上遍历算法的相比(参考博文“后缀数组的自底向上(bottom-up)遍历算法”),对后缀树的Bottom-Up遍历要直接一些。后缀树的Bottom-Up遍历过程是:如果孩子结点是内部结点,对这些孩子结点按照从左到右的词典序(lexicographic order原创 2011-07-24 11:55:26 · 4828 阅读 · 0 评论 -
Boyer–Moore–Horspool文本匹配算法(BM算法的简化版)
英语里有句习语叫"find a needle in a haystack",译成中文叫"大海捞针"(原意是在一堆干草中寻找一根针)。计算机中的文本匹配(string matching)就是要解决怎样在一段很长的文本中找到符合要求的一个子串,该子串通常叫模式串(pattern),也就是对应我们要找的“针”。常用的文本精确匹配(exact string matching)算法有蛮力法(brute-f原创 2011-06-19 13:02:00 · 11762 阅读 · 1 评论 -
Boyer-Moore文本匹配算法(联合使用KMP和Horspool算法)
Boyer-Moore除了考虑Horspool算法(参考笔者的另一篇专门介绍Horspool算法的文章)的坏字符之外,还将模式串中已经匹配成功的后缀(叫做好后缀,good suffix)考虑进来,从而得到全部已经知道的启发信息(heuristic)。因此从理论上来说,BM算法应该是性能最佳的一个算法,实践中也证明了这一点。 这也是为什么BM算法经常用作精确匹配算法里面的性能测试基准算法。例如,在通原创 2011-06-21 22:44:00 · 4087 阅读 · 0 评论