POJ3349_Snowflake Snow Snowflakes
描述
有n片雪花,每个雪花使用6个整数来描述其每个角。比如1,2,3,4,5,6,描述可以从任意一个角开始,比如上面的雪花也可以被描述为2,3,4,5,6,1,也可以是逆序的如3,2,1,6,5,4只要按一个圈来描述六个角就行。
现在,需要判断给出的雪花描述里面有没有相同的。
数据范围
0 < n ≤ 100000,雪花用正整数描述,小于10000000
思路
哈希做法,由于雪花的描述和顺序无关,我们构造和顺序无关的哈希函数,蓝书上的构造方法是这样的:
(∑ai + Πai) % P
其中ai表示雪花各个角的数字描述,P是一个大质数。
使用链表数组来存储雪花下标,以便于如果发现两片雪花的哈希值相等,我们可以进行进一步的比较。
这里,我取的P = 100003,从期望上来说,可以把每片不同的雪花分开。
比较使用的比较暴力的比较方法,轮转比较6次,再反向轮转比较6次,虽然很繁复,但考虑实际上比较的次数接近于常数次,所以比较的时间复杂度可以忽略。
整个算法接近于O(n)。
解决
1 |
|
备注
在POJ上用C++提交会因为fill(hash, hash + N, vector < int > {})这句话报编译错误,可能不支持C++11,换成G++就好了。
因为mult没开long long而wa了几发。
CH1401_兔子与兔子
描述
有一个长度为S的小写字符串序列,查询Q次,每次指出两个区间,询问这两个区间内的字符串是否相等。
数据范围
1 <= S, Q <= 1e6
思路
朴素思想进行字符串比较的复杂度是O(QS),使用字符串哈希的方法可以将复杂度降至大致为O(Q)。
字符串哈希的做法是这样的,首先给定一个数p,一般为131或1331(并不知道由来,只知道有这个传统),然后将字符串看作p进制数。
遍历字符串,每一位的哈希值等于上一位哈希值乘p加本位的字符值,再设置一个辅助数组,其第i位的值等于p的i次方。
以上操作均不处理溢出问题,权当取模。
这样,取出区间(l, r)哈希值的做法是:hashr - hashl-1 * pr-l+1
如果字符串的哈希值相等,我们认为它们相等,这里为了保险,我加上了还需要判断两个字符串长度一致。
据说实际上这种方法出现错误的概率还是很小的,如果担心出现问题,还可以设置多个p值,当多个p值下的哈希值都一致的情况下才认为相等。但对于这道题来说,p取131足够了。
解决
1 |
|
POJ3974_Palindrome
描述
找出长度为N的字符串S的最长回文子串的长度。
数据范围
1 < N < 1e7
思路
回文数组有两种,长度为奇数的和长度为偶数的,长度为奇数的回文数组是以某个位置为中心,向两侧延申时对应位置的字符相等,长度为偶数的回文数组则是以中间两个字符的间隔为中心的。
可以通过遍历两次,第一次找出长度为奇数的最长回文数组,第二次找出长度为偶数的。
为了支持正序的子序列和逆序的子序列比对,需要建立一个正序子序列哈希数组,一个逆序哈希数组。
解决
1 |
|