2020 Multi-University Training Contest 8 hdu6863 Isomorphic Strings(哈希/kmp 循环同构 因数分布/约数分布)

题目

a、b循环同构是指两个串的最小表示法相同,

也可以理解成把a变为原来的两倍aa后,其中按照a的长度尺取,能够找到b

样例数T<=1e3,每次给一个长度为n(n<=5e6)的小写字母串,

问是否存在一个n的因数k(k>1),把长为n的串从头到尾,

每n/k个就分离出一个串,分出s1,...,sk共k个串后,这k个串是循环同构的

若存在输出Yes,否则输出No

保证sumn<=2e7

思路来源

官方题解

题解

2020 Multi-University Training Contest 8 hdu6863 Isomorphic Strings(哈希/kmp 循环同构 因数分布/约数分布)_第1张图片

粘一发官方题解,大力莽n的约数,约数的个数分布,有一张经典的图

2020 Multi-University Training Contest 8 hdu6863 Isomorphic Strings(哈希/kmp 循环同构 因数分布/约数分布)_第2张图片

本题中,n<=5e6的时候,max{d(n)}=384,可以用枚举倍数O(nlogn)现打表

 

首先,预处理前缀哈希值,这样[l,r]就能通过[1,l-1]和[1,r]算

然后,肯定要大力莽n的因数,设字符串长度为k,k

第一段有k种解读方法,把这k个哈希值插到桶里,

后面的(n/k-1)段,只需O(1)检查这个值在不在桶里,

对于每个k,复杂度是O(k+n/k)的,所以总的复杂度是O(n的约数和)的,大概在2e7级别

但考虑到单哈希不一定能行,本题标程采用了三哈希,再乘个3

心得

网友乱搞kmp,O(n*n的约数)都搞过去了,虽然复杂度不大对

2020 Multi-University Training Contest 8 hdu6863 Isomorphic Strings(哈希/kmp 循环同构 因数分布/约数分布)_第3张图片

然而,感觉自己哈希姿势水平明显不如网友,

单哈希被卡,手写双哈希暴力找还T了,

 

实际上,可以采用这种第X次哈希,就把桶里的值都赋值为X的方式,

就做到O(1)了,还不用初始化,华师这波板子i了i了

代码

#include
using namespace std;
#define pb push_back
typedef long long ll;
namespace RA{
    int rnd(int p){return 1ll*rand()*rand()%p;}
    int rnd(int L,int R){return rnd(R-L+1)+L;}
}
const int N=5e6+5,K=3,M=1e7+5;
const ll bs=29;
int t,n,c;
int hs[K][N],pw[K][N],tong[M];
char s[N];
int mod[K] = {
    //1000003,
    //1000037,
    2000039,
    5000011,
    7000061
};
void init(){
    for(int k=0;k

 

你可能感兴趣的:(#,哈希,#,杭电多校,哈希,kmp,循环节,三哈希,桶)