P3538 题解

P3538

[POI2012]OKR-A Horrible Poem

思路

先暴力。对于每个询问,用 \(O(\sqrt{len})\) 枚举区间长度 \(len\) 的因数 \(i\),再一个一个位置比较两个字符串 \(\frac{len}{i}\) 次判断。复杂度 \(O(qn\sqrt n)\)

字符串哈希, \(O(1)\) 判断字符串是否相等。

性质:判断一个字符串 \([1,s]\) 是否有长度为 \(len\) 的循环节,通过判断 \([1,S-len]\) 是否等于 \([1+len,S]\) 即可。

这样就可以 \(O(1)\) 判断每个可能的长度,复杂度 \(O(q\sqrt n)\)

现在时间的问题在枚举可行的因数。

但其实可以优化。我们只需要处理出 \(len\) 的质因数,让 \(len\) 不断除以质因数直至 \(1\),这个过程中就可以得出 \(len\) 的每个因数。

由于每次最小可以除以 \(2\),所以 \(len\) 每次操作至少缩小一半,这个复杂度是 \(O(\log n)\) 的。预处理出每一个数最小的质因子,这样在对质因数分解的时候,当前 \(len\) 自身不断的除以 \(len\) 的最小的质因子,就可以遍历 \(len\) 所有的质因数。在询问前 \(O(n)\) 预处理出每一个数最小的质因子。

这样复杂度 \(O(n+q\log n)\)

code

void sovle(){
	l=read();r=read();ans=s=r-l+1;
	if(gethsh(l,r-1)==gethsh(l+1,r)){
		printf("1\n");
		return ;
	}
	while(s>1){
		if(gethsh(l,r-ans/f[s])==gethsh(l+ans/f[s],r))ans/=f[s];
		s/=f[s];
	}
	printf("%d\n",ans);
}
posted @ 2024-05-10 20:03  yhddd  阅读(12)  评论(0)    收藏  举报