1457:Power Strings
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 1280 通过数: 515
【题目描述】
原题来自:POJ 2406
给定若干个长度 ≤106 的字符串,询问每个字符串最多是由多少个相同的子字符串重复连接而成的。如:ababab 则最多有 3 个 ab 连接而成。
【输入】
输入若干行,每行有一个字符串,字符串仅含英语字母。特别的,字符串可能为 . 即一个半角句号,此时输入结束。
【输出】
【输入样例】
abcd
aaaa
ababab
.
【输出样例】
1
4
3
思路:假设 b = 3,数的范围为0-63 (代码中实际情况是,b=131,mod = 1<<31,数据类型为unsigned long long)
对于字符串abcabc:
index: 0 1 2 3 4 5
arr: a b c a b c
hash: 56 61 41 34 11 3
(计算公式:hash[i]=hash[i+1]*b+s1[i]-‘a‘+1) 这里面有个问题是:因为数的范围为0-63 ,最大为63,可能存在数的溢出,比如:
从左往右,a->c这一步,hash[2] = hash[3] * 3+‘c‘-‘a‘+1 =34 * 3+2+1= 105。105大于63,这么办?
在计算机中会自动取模(也就是取余数):105% 64=41。其他 hash值都是这么计算的,每步都会取余数的。
同样,power的计算也是如此:3 9 27 17(81%64) …
那么计算机怎么判断前三个字符(“abc”)与后三个字符(“abc”)相等呢?取模后计算会不会出现负值?
后三个字符:tmp0 = hash[3]-hash[6] * power[3] = 34 - 0 * 27 = 34
前三个字符:tmp1 = hash[0]-hash[3] * power[3] = 56 -34 * 27 = ? 。这里34* 27实际是(34* 27)%64=22,所以56-22=34。
所以tmp0=tmp1。(程序中用函数封装)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
const