您的位置:首页 > 其它

acm算法思想总结

2017-04-02 13:45 246 查看
能解释一下单调栈吗?{

单调栈就是维护栈内元素保持单调性,单调递增或单调递减。

比如给一个数组,大小为5,元素分别是 1 3 2 5 4 我要维护单调递增的栈,

此时栈内元素为空,从数组开头扫描,最开始是1,因为栈空,所以直接加入到栈内,

接下来是3,3比栈顶元素1要大,保持单调递增,加到栈内,接下来是2,比栈顶元素

3 要小,弹出3,栈顶元素为1,2比1大,此时可加入到栈顶。可以知道2往左边最远

可扩展到1这个位置,不包括1,即1之后的元素到2之前都大于等于2。后面来了5, 5

比2大,加到栈内,最后是4, 4 比5小,弹出5, 4 比2大。所以能够知道2之后的元素

到4之间都大于或等于4。

}

能解释一下单调队列吗?{

单调队列就是维护队列里元素的单调性,单调递增或者单调递减。

比如给一个数组,大小为5,元素分别是 4 1 2 3 5, 我现在给一个滑动窗口,大小

为3,滑动窗口从数组开头开始滑动,每次滑动找出窗口中的最大值。比如刚开始是

4 1 2 ,最大值为4 ,接下来是1 2 3, 最大值是3 ,接下来是2 3 5, 最大值是5.

如果每次滑动一次,就循环去找窗口中的最大值,复杂度是O(n*m), 效率过低,那么用

单调队列可以实现O(n)的实现。

设置一个队列,开始时为空,把4加入队列,然后到1,加入到队列中,因为1可能是以1

为开头的窗口元素。

继续是2, 2 比1小,弹出1,说明1不可能成为任何一个窗口的最大值,2加入到队列。

前3个元素已经访问完,最大值为单调队列的队首元素4。接下来到3,

3 比2大,弹出2,比4小,加到队尾。因为4距离3的大小已经超过了窗口大小,则需要

从队首移除。此时队首变成了3,即此时窗口最大值为3,对应1 2 3 这个窗口。最后是

5, 照此规则进行。

}

解释一下字典树?{

字典树可用于对多个字符串建立一棵树,每个节点对应一个字符,树的某些路径可共用。

比如给4个字符串:abc abb acb acd 字符串abc建立了一条路径,每个节点对应的字符

是a b c, 到abb时,ab得到了共用,需要在后面建立一个c字符的节点。再是acc, a

得到了共用,需要在其后建立一个c字符的节点,再建一个b字符的节点。不过abb和acb

并不能共用a和最后一个b字符对应的节点,只能共用相同的前缀。最后是acd,照此原则。

建立好一棵字典树之后。就可以查询某个字符串是否在字典树中。

字典树的应用: 串的快速检索,对串排序,查询串的公共前缀。

优点: 节省空间。查询速度快。

拓展{

可持久化字典树

假如给一个数组,大小为10,然后把数按照比特位插入到可持久化字典树中,

假如所有的数不超过10000,最高位从第16位开始,从高位往低位开始建成一条

路径。每个节点只有0或1 。第2个数会利用第一个数的节点的相关信息。第3个数会利用

前面构建的字典树的信息。直到所有树插入进去。如果要查询某个数是否在第3到第8个数

有出现,则第1 , 2 个数不能包含在内。如果只是普通的字典树,那么不可能实现这种

区间的查询。

}

}

二分图解释一下原理?{

举个例子,我有5件上衣,6条裤子,有一些限制条件,假如把上衣编号为a,b,c,d,e

裤子编号为 1,2,3,4,5,6 限制条件比如a可以和1,3,5 搭配,不能和其他裤子搭配。

b也只能其中某些裤子搭配。每件上衣和裤子只能使用一次,那么最多可以得到多少

套装。这就是一个二分图匹配问题。假如现在a和1搭配了,当搜c的时候,发现c可以和

1 搭配,1保存的匹配对象是a,a也可以和2搭配,且2现在没有匹配对象,那么可以取消

a和1这条边,将a和2连一条边,c和1连一条边,这样匹配数就增大了。直到不能再增加

匹配数为止。

}

极大团{

团里的每个节点都与其他节点有相连,即这个团有 N*(N-1)/2 条边。

}

迪杰斯特拉算法{

迪杰斯特拉算法是一种最短路算法,可以求其他节点到某一节点的最短路。

假如有5个点,1是起始节点,然后去找距离1最近的节点添加进来,比如是3,接着在

2,4,5 中找距离集合最短距离的点,即2到1 3, 4 到1 3 ,5到1 3 中最短的距离。再

将其添加进来。直到找完所有的点。 添加进一个点时,就更新所有到这个集合未添加的点

的最小值与这个点的距离的较小值。

朴素的复杂度是O(n^2),如果用优先队列优化的话,可以达到O(nlg(n))。

}

spfa(最短路径快速算法){

也是一种最短路算法。利用到队列。

假如有5个点,1是起始节点,设置数组D[], D[i]代表点i到1的最短距离,开始时置非

常大的值。先将1加入到队列,然后开始从队列取出队首元素,此时是1,找到与1相连

的点,比如是2和3, 更新D[2],D[3]的最小值,将2,3 加入队列。再取队首元素。此时

是2,假如3,4,5 与2相连,更新D[3],D[4],D[5]的最小值,可能会出现D[3]比之前要小。

因为3在之前已经加入了队列,则此时不需要再将其加入队列。直到所有节点的D值不发生

变化或队列未空时就结束算法。

朴素的复杂度为(VE)。但稳定性不佳。用优先队列优化可达O(nlg(n))

适用于稀疏图,不适于稠密图。

}

弗洛伊德算法{

一般三层循环,复杂较高,约为O(n^3),但是它可以求出每两个点之间的最短距离。

比如要求D[i][j]的最短距离,可以用一个中间节点k,利用D[i][k]+D[k][j]来更新。

所以三层循环分别对应i,j,k。

}

强连通算法{

强连通算法可以找到强联通分量,每个分量相当于一些点的集合。这个集合的每两个

点可以互达。比如有一个有向环,1->2->3->1 则1 2 3是一个连通分量, 因为他们都

可以互达。设置两个量 dfn 和 low, dfn代表这个节点第一次被访问时的顺序编号,

low代表从这个节点一直搜下去可以搜到的最小节点的编号。如果low比dfn小,说明

它搜到了之前已经访问过的节点,形成了环。于是他就属于某一个分量。

}

双连通算法{

跟强连通差不多。

}

网络流算法{

考虑一个模型,有n个点m条边的图,每条边设置了最大容量和流量。有一个源点和汇点。

比如有5个点,1是源点,5是汇点。每次从1开始找一条可到达5的路径,路径要保证能

有流量传输。然后加上流量后,修改这条路上的边的流量值。一直循环下去,直到5

不能增加流量。

}

Prim算法{

Prim算法是实现最小生成树。

假设有5个点的图。最开始选择1作为起点。现在去找2,3,4,5 中到1的最短边,加上这条边

的长度,并把选中的点加进集合。比如选择了3,接下来再找2,4,5 中距离集合最短的距离。

再将选中的点加进来。直到所有的点加进集合。

复杂度为O(n^2) 适合稠密图。

}

克鲁斯卡尔算法{

也是实现最小生成树的算法。

将所有的边进行排序。对于某条边,两个点设为a,b,用并查集查找到a和b所属树的根节点。

如果两者的根节点相同的话,说明a,b在同一棵树里,加进这条边会形成环。没必要。

如果两者的根节点不同,说明a,b在不同的树里,可以加入a->b这条边。将两颗树合并。

直到所有的节点加进来。

复杂度为O(E*lg(E)) 适合稀疏图。

}

后缀数组怎么实现?{

以字符串 abcab为例,刚开始以一个字符来排序,abcab对应的大小分别为 1 2 3 1 2,

再在第一次的基础上比较的字符串倍增,按照两个连续的字符比较,第一个a和第二个a

之前的排名大小都是1,发现他们后一个字符都b, 两者的排名还是置为1,

第一个b和第二个b之前的排名是2,现在发现第二个b后面没有字符,则第二个b的排名

在第一个b之前。一个设为2,一个设为3,剩余的比较也是如此。那么现在的排名

分别是1 3 4 1 2, 再比较四个字符。直到所有的排名已区分开。

采用倍增的方式,所以复杂度是O(nlg(n))

}

ac自动机怎么实现?{

ac自动是在字典树上进行字符串匹配。如果要进行匹配的话,可以先了解一下KMP算法

(略过),假如有两个字符串aa baaa插入到字典树中。第一个字串的a的失配指针指向

根,第二个字符串的失配指针指向根(画图会比较好解释。。。)

}

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm