上一页 1 ··· 43 44 45 46 47 48 49 50 51 ··· 85 下一页
  2012年2月3日
摘要: POJ_3261 这个题目和POJ_1743差不多,但需要求的是重复至少K次的子串。 我们可以通过二分子串的长度k来做,这时就将题目变成了是否存在重复次数至少为K次且长度不小k的字符串。首先我们可以把相邻的所有不小于k的height[]看成一组,这组内有多少个字符串,就相当于有多少个长度至少为k的重复的子串。 之所以可以这么做,是因为排名第i的字符串和排名第j的字符串的最长公共前缀等于height[i],height[i+1],...,height[j]中的最小值,所以把所有不小于k的height[]看成一组就保证了组内任意两个字符串的最长公共前缀都至少为k,且长度为k的前缀是每个字符串... 阅读全文
posted @ 2012-02-03 18:35 Staginner 阅读(863) 评论(0) 推荐(0) 编辑
摘要: POJ_1743 搜到的题解基本都是说去找最长的不重叠的重复的子串,但是我一直对题目描述里面的那个const带有一点纠结,比如88 88 88 1 1 1 88 88 88 1 1 1,我觉得要按const去理解的话应该输出3的,但题解都是输出的6。不过意在练后缀数组的使用,就没有太顾及这些问题了。 这个题目关键的地方有两个:第一,重复的子串一定可以看作是某两个后缀的公共前缀,第二,把题目转化成去判定对于任意的一个长度k,是否存在长度至少为k的不重叠的重复的子串。 转化成判定问题之后,就可以二分去解答了。在验证判定是否正确时,我们可以把相邻的所有不小于k的height[]看成一组,然后去... 阅读全文
posted @ 2012-02-03 16:43 Staginner 阅读(610) 评论(0) 推荐(0) 编辑
  2012年2月2日
摘要: SPOJ_705 历经好几天学习倍增算法的折磨,现在终于能够自己把倍增算法的代码敲出来了。 对于倍增算法的代码的一些解释可以参考我的另一篇文章:http://www.cnblogs.com/staginner/archive/2012/02/02/2335600.html 这个题目关键在于要认识到任何一个子串都必然是某一个后缀的前缀,对于任意一个后缀i,它能够贡献出的新的子串的数目等于n-i-height[rank[i]]。其中n-i是其所有的子串的数目,其中由于它和排名前一位的字符串有height[rank[i]]个字符的公共前缀,因此其中有height[rank[i]]个子串是和前面... 阅读全文
posted @ 2012-02-02 17:51 Staginner 阅读(528) 评论(0) 推荐(0) 编辑
摘要: 一开始看“小罗”写的论文和模板真的云里雾里,理解起来十分困难,后来结合一个百度贴吧里面的学习笔记总算是把倍增算法的代码的意思搞懂了,于是后面自己也写了一份对“小罗”倍增算法代码的注释,希望能对各位正在学习后缀数组的同僚带来一点帮助。 另附上百度贴吧那篇文章的链接:http://tieba.baidu.com/f?kz=754580296int wa[maxn],wb[maxn],wv[maxn],ws[maxn];int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];} //就像论文所说,由于末尾 阅读全文
posted @ 2012-02-02 12:18 Staginner 阅读(13467) 评论(6) 推荐(19) 编辑
  2012年1月30日
摘要: POJ_1724 这个题目可以直接将SPFA中的dis[]变成二维的dis[i][k]表示到第i个点花费为k时的最短路,但如果直接做SPFA会超时,需要加一个剪枝:设mind[i]表示到第i个点的用于剪枝最短路,mink[i]表示第i个点的用于剪枝的最小花费,如果在SPFA的过程中走到了第i个点的路径长为d花费为k,那么如果d>=mind[i]&&k>=mink[i],这时就进行剪枝,如果d<mind[i]&&k<mink[i]就更新mind[i]与mink[i]的值,并将这个点(i,k)入队,其余的情况也要将(i,k)入队。 这个题目还 阅读全文
posted @ 2012-01-30 22:54 Staginner 阅读(412) 评论(0) 推荐(0) 编辑
摘要: ZOJ_1729 实际上就是要求去求给定字符串的“最小表示”。#include<stdio.h>#include<string.h>#define MAXD 200010int N;char b[MAXD];void solve(){ int i, j, k, p1, p2; scanf("%d%s", &N, b); for(i = N; i < 2 * N; i ++) b[i] = b[i - N]; p1 = 0, p2 = 1; for(;;) { for(k = 0; k < N; k ++) i... 阅读全文
posted @ 2012-01-30 00:53 Staginner 阅读(252) 评论(0) 推荐(0) 编辑
  2012年1月28日
摘要: POJ_1059 由于题目说了最后掷骰子的次数不会超过1000,所以直接模拟掷骰子的过程即可。#include<stdio.h>#include<string.h>#define MAXN 1010#define MAXD 110#define MAXP 10int P, die[MAXN], g[MAXD], turn[MAXP], a[MAXP];void init(){ int i, j, k; for(i = 0; ; i ++) { scanf("%d", &k); if(!k) break; die[... 阅读全文
posted @ 2012-01-28 22:12 Staginner 阅读(393) 评论(0) 推荐(0) 编辑
摘要: POJ_3691 这个题目可以直接在生成的trie图的“安全部分”进行dp,用f[i][j]表示第i步走到第j个节点时,最少repair了几个基因。 具体的建立trie图的思想可以参考《Trie图的构建、活用与改进》这篇文章。#include<stdio.h>#include<string.h>#define MAXD 1010#define INF 0x3f3f3f3fchar gene[MAXD], b[30];int f[MAXD][MAXD], next[MAXD][4], flag[MAXD], N, e, P[MAXD], q[MAXD];void add( 阅读全文
posted @ 2012-01-28 20:13 Staginner 阅读(230) 评论(0) 推荐(0) 编辑
摘要: POJ_2778 如果做过POJ_1625的话,dp思路还是比较容易想到的,如果没做过的话可以参考一下《Trie图的构建、活用与改进》这篇文章的思想。 但遇到的一个问题是,对于如此巨大无比的n我们要怎么去优化呢?这个还是依赖于动态转移方程的形式。我们可以看出这个题目的动态转移方程一个确定的和式方程,即对于任意第i+1阶段的状态j,都可以表示成f[i+1][j]=a1*f[i][1]+a2*f[i][2]+...+ax*f[i][x],那么所有x个状态的转移方程就可以用一个大的矩阵的乘法表示出来,具体的构造方式如下图: 这样自然就可以用二分矩阵来加快运算了。 不过这个算法虽然能够AC,但... 阅读全文
posted @ 2012-01-28 00:20 Staginner 阅读(403) 评论(0) 推荐(0) 编辑
  2012年1月27日
摘要: URAL_1158 一开始实在想不出什么思路,后来看了《Trie图的构建、活用与改进》之后终于理解了所谓的AC自动机dp,如果你也和我一样看不懂别人的解题报告的话,不妨看看这篇文章,一定会有所收获。 其实,如果我们把每个字符当作一个节点,然后把生成字符串的过程看作是在节点间行走的话,那么可以想象,如果0时刻从根节点出发开始行走的话,那么当前的合法字符串的数量,应该等于该时刻到达每个节点的可走路径条数的总和,因为一条路径对应的就是一个字符串。 但是有一点很棘手,就是怎么才能控制自己走过的路径一定不含非法的字符串呢?trie图为我们提供了这个方便。如果我们把“行走”的过程看成在trie图上行... 阅读全文
posted @ 2012-01-27 21:18 Staginner 阅读(471) 评论(0) 推荐(0) 编辑
上一页 1 ··· 43 44 45 46 47 48 49 50 51 ··· 85 下一页