上一页 1 ··· 42 43 44 45 46 47 48 49 50 ··· 85 下一页
  2012年2月7日
摘要: POJ_2318 可以二分线段的位置,然后利用叉积去判断点在线段的左边还是右边即可。#include<stdio.h>#include<string.h>#define MAXD 5010int N, M, X1, Y1, X2, Y2, a[MAXD], b[MAXD], h[MAXD];long long int det(int x1, int y1, int x2, int y2){ return (long long int)x1 * y2 - (long long int)x2 * y1;}void init(){ int i, j, k; a[0] = b[ 阅读全文
posted @ 2012-02-07 06:46 Staginner 阅读(236) 评论(0) 推荐(0) 编辑
  2012年2月6日
摘要: POJ_3693 这个题目和SPOJ_687差不多,基本的思路可以参考罗穗骞的论文和我的SPOJ_687的题解http://www.cnblogs.com/staginner/archive/2012/02/06/2340521.html。 对于字典序最小这一条件,我没有想到太好的解决策略,只是默认r[L*i]在第一循环节内,然后向前枚举第一个循环节的首字符的位置,如果此时repetition number和max相等,那么就将这个字符串记录下来,如果比max大,就更新max,并把记录的可能的解清零后再将这个字符串记录下来,如果比max小就直接break,而不用再继续向前枚举第一个循环节首字符 阅读全文
posted @ 2012-02-06 21:47 Staginner 阅读(1243) 评论(0) 推荐(0) 编辑
摘要: SPOJ_687 这几天写了好多字的解题报告了,这次就偷懒一点吧,其实基本的思路在罗穗骞的论文里已经说得比较清楚了。 其中值得一提的是,论文里说过这样一句话“所以只需看字符r[L*i]和r[L*(i+1)]往前和往后能匹配到多远”,对于往后能匹配到多远,这个直接根据最长公共前缀就能很容易得到,而对于往前能匹配到多远,我们当然可以一开始就把字符串反过来拼在后面,这样也能根据最长公共前缀来看往前能匹配到多远,但这样效率就比较低了。 其实,当枚举到合适的子串长度时,我们在枚举r[L*i]和r[L*(i+1)]的过程中,必然可以出现r[L*i]在第一个循环节里,而r[L*(i+1)]在第二个循环节.. 阅读全文
posted @ 2012-02-06 19:02 Staginner 阅读(1626) 评论(1) 推荐(1) 编辑
摘要: POJ_3368 本来想找个RMQ问题练一下今天刚学的ST算法,结果这个题我用ST做不出来,所以只好又用回线段树解法了。 当然dicuss里面有人说也可用ST去做的,我就只说一下我用线段树去做的思路吧。 首先,如果a[i]==a[j]的话,自然输出j-i+1就可以了,如果a[i]!=a[j],如果我们直接查询a[i]、a[j]之间的所有整数出现的频率的最大值,显然是有问题的,因为这样可能会将值等于a[i]或a[j]但序号并不在i~j的范围的整数也统计在内。于是,我们便有了一个思路,在统计a[i]、a[j]之间的所有整数出现的频率的最大值之前,能不能修改一下a[i]和a[j]出现的频率,使... 阅读全文
posted @ 2012-02-06 15:41 Staginner 阅读(442) 评论(0) 推荐(0) 编辑
摘要: POJ_3415 不妨设首字符在第一个字符串里的后缀为A类后缀,首字符在第二个字符串里面的后缀为B类后缀。首先要将两个字符串合并为一个字符串并用分隔符隔开,然后处理出height数组。对于任意一个A类后缀i,和任意一个B类后缀j,假设其公共前缀的长度为k,这两个后缀所能贡献出的S集合里的元素的数目就是k-K+1,当然前提是k>=K。 但是按这样的思路,即便求k时利用height数组的性质及RMQ问题的算法,最后也只能做到O(n^2)复杂度。于是必须优化计算k的过程的时间复杂度。 接下来先要对前面的思路做一个等价的转化,我们选择顺序遍历两次height数组,第一次遍历的时候如果遇到B类后缀 阅读全文
posted @ 2012-02-06 01:34 Staginner 阅读(723) 评论(0) 推荐(0) 编辑
  2012年2月5日
摘要: SPOJ_220 这个题目和POJ_1743很像,POJ那个题是去找最长的不重叠的重复字串,而这个题目是要求找到一个字符串,使得其是各个字符串的最长的不重叠的重复字串。 因此,整体的思路还是基本相同的。首先要将若干字符串合并成一个字符串并用分隔符隔开。然后二分所求字符串的长度k,并顺序遍历height数组,将相邻的值不小于k的height[]分成一组,对于组内的后缀按首字符所在的字符串的不同,一一去判断sa[]的最大值和最小值之差是否不小于k,如果不小于k就说明在这个字符串中存在长度为k的不重叠的且至少出现两次的子串。#include<stdio.h>#include<str 阅读全文
posted @ 2012-02-05 13:28 Staginner 阅读(329) 评论(0) 推荐(0) 编辑
摘要: POJ_1226 这个题目可以枚举长度最小的字符串的所有子串,然后暴搜。但为了练一练后缀数组,所以就用后缀数组写了。#include<stdio.h>#include<string.h>#define MAXD 20100char b[110];int N, M, h[110], f[MAXD], r[MAXD], rank[MAXD], sa[MAXD], height[MAXD], ws[MAXD], wv[MAXD], wa[MAXD], wb[MAXD];void init(){ int i, j, k, x = 128; k = 0; for(i = 0; i 阅读全文
posted @ 2012-02-05 02:09 Staginner 阅读(305) 评论(0) 推荐(0) 编辑
  2012年2月4日
摘要: POJ_3294 首先,我们可以把这几个序列合并成一个序列,并且在之间加入一些分隔符,但这些分隔符最好用不一样的且不同于序列中的字符的整数表示,这样在后面寻找后缀间的公共前缀时就避免了把分隔符也匹配进去的情况。 接着,我们只要二分字符串的长度k,并依height[]的值将height[]看成若干组,每组中height[]的值均不小于k。如果这一组中涵盖的不同的序列的数量大于N/2,那么就说明满足题意的字符串的长度至少为k。 找到k的值后再遍历一遍height数组,将符合要求的前缀的首字符的位置记录下来即可,根据首字符的位置和k的值就可以输出满足题意的字符串了。同时,由于是遍历height数组, 阅读全文
posted @ 2012-02-04 19:22 Staginner 阅读(278) 评论(0) 推荐(0) 编辑
摘要: POJ_2774 这个题目实际上就是去求最长公共子串,如果用gets读字符串会WA,所以还得用scanf。 首先,我们可以把两个字符串合并,并在中间加一个’$’以避免某个公共前缀同时在两个字符串中。用后缀数组的做法处理出height数组后,扫描一遍height[],如果sa[i-1]和sa[i]的位置分别在两个字符串中且height[i]大于max的话,就更新一下max。最后输出max的值即可。 可以证明,这样求得的解是合理的。对于合并后的字符串的后缀i、j,不妨设i<j,且i的首字符在第一个字符串里,j的首字符在第二个字符串里面,假设i、j的最长公共前缀为k,对于按字典序排好的各个后缀 阅读全文
posted @ 2012-02-04 13:10 Staginner 阅读(296) 评论(0) 推荐(0) 编辑
摘要: URAL_1297 找回文串最直观的一个算法就是枚举中间的点,然后向两边查找,看最后能拓展多远,但是这样是n^2的算法,利用后缀数组可以达到O(nlogn)的复杂度。其实在枚举中间的点之后,向外拓展多远是取决于两个方向相反的字符串的公共前缀的,而如果利用后缀数组我们就可以在O(logn)的时间内找到这两个字符串公共前缀最长是多少。 下面面临的一个问题就是两个字符串是方向相反的,为了能够使两个字符串同向,我们可以把原序列翻过来的序列插入到原序列后面,这样这个字符串里面顺序看过去就既包含了原序列的正向的字符串,同时也包含了原序列的反向的字符串。 但是,如果这样去找后缀间的公共前缀的话,我们会发.. 阅读全文
posted @ 2012-02-04 10:26 Staginner 阅读(430) 评论(0) 推荐(0) 编辑
上一页 1 ··· 42 43 44 45 46 47 48 49 50 ··· 85 下一页