zoukankan      html  css  js  c++  java
  • 【BZOJ】2795: [Poi2012]A Horrible Poem

    题意

    一个长度为(n(n le 500000))的字符串(s),给(q(q le 2000000))个询问,每个询问给一个区间([l, r]),求这个区间内最短的循环节。

    分析

    分析以下可以知道:

    1. 假设循环节长度为(len),则(s[l, r-len]=s[l+len, r])
    2. (len|(r-l+1))
    3. 如果(len)是循环节,则(len * p)也是循环节((len * p|(r-l+1)))

    题解

    首先判两个串是否相等用hash即可。
    根据(1, 2)我们很容易得到(O(qn^{0.5}))的做法。
    可是由于性质(3)的存在,我们先分解((r-l+1))的质因数,然后依次考虑删去质因数即可。
    复杂度(O(qlogn))

    #include <bits/stdc++.h>
    using namespace std;
    inline int getint() {
    	int x=0, c=getchar();
    	for(; c<48||c>57; c=getchar());
    	for(; c>47&&c<58; x=x*10+c-48, c=getchar());
    	return x;
    }
    const unsigned int N=500005, mo=1e9+7;
    int p[N], cnt, m[N], bg[N];
    unsigned int a[N], po[N];
    void init(int n) {
    	for(int i=2; i<=n; ++i) {
    		if(!bg[i]) {
    			bg[i]=i;
    			p[cnt++]=i;
    		}
    		for(int j=0, t; j<cnt; ++j) {
    			t=p[j]*i;
    			if(t>n) {
    				break;
    			}
    			bg[t]=p[j];
    			if(i%p[j]==0) {
    				break;
    			}
    		}
    	}
    }
    inline bool check(int a, int b, int c, int d) {
    	return m[b]-m[a-1]*po[b-a+1]==m[d]-m[c-1]*po[d-c+1];
    }
    int main() {
    	int n=getint();
    	init(n);
    	po[0]=1;
    	for(int i=1; i<=n; ++i) {
    		m[i]=m[i-1]*mo+getchar();
    		po[i]=po[i-1]*mo;
    	}
    	int q=getint();
    	for(; q--; ) {
    		int l=getint(), r=getint(), len=r-l+1;
    		for(int x=len; x>1; ) {
    			int y=bg[x];
    			for(; len%y==0 && check(l, r-len/y, l+len/y, r); len/=y);
    			for(; x%y==0; x/=y);
    		}
    		printf("%d
    ", len);
    	}
    	return 0;
    }
  • 相关阅读:
    JVM内存的划分
    劝学
    java中switch的用法
    方法传递参数的分类
    ajax缓存机制
    vuex
    keep-alive
    路由滚动行为scrollBehavior
    vue等
    防止刷新路由后参数消失
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985761.html
Copyright © 2011-2022 走看看