zoukankan      html  css  js  c++  java
  • P3538 [POI2012]OKRA Horrible Poem

    给定一个串和多个区间,要求出区间最短循环节长度

    1.判断一个字符串是该区间的循环节,可以O(1)hash判定,设枚举的循环节长度为t,判断[l,r-t]与[l+t,r]相等否即可
    2.长度x是区间的一个循环节,y是x的倍数且是区间长度的约数,那么y也是循环节
    3.对于多组询问的分解质因数,我们不需要全部预处理出来,也不需要每次都用试除法去试,我们可以用求出每个数的最小质因子设为v[x],然后用x=x/v[x],这些v[x]就是原数x的质因子集合,比试除法快很多

    typedef unsigned long long ull;
    const int N = 5e5 + 79;
    const ull base = 13131;
    int n, x, y, q;
    ull p[N], H[N];
    char s;
    inline bool check(int l, int r, int x, int y) {
    	return H[r] - H[l - 1] * p[r - l + 1] == H[y] - H[x - 1] * p[y - x + 1];
    }
    
    
    int v[N],prime[N],t;
    inline void EulerSieve(int mx){
    	rep(i,2,mx){
    		if(!v[i]){
    			v[i]=i;
    			prime[++t]=i;
    		}
    		rep(j,1,t){
    			if(1ll*prime[j]*i>mx||prime[j]>i) break;
    			v[i*prime[j]]=prime[j];
    		}
    	}
    }
    
    int a[N];
    inline void solve(int x, int y) {
    	int len = y - x + 1;
    	int cnt=0;
    	while(len != 1) {
    		a[++cnt] =v[len];
    		len/=v[len];
    	}
    	len=y-x+1;
    	rep(i,1,cnt){
    		int t=len/a[i];//µ¥¸öÑ­»·½Ú³¤¶È 
    		if(check(x,y-t,x+t,y) ){
    			len/=a[i];
    		}
    	}
    	out(len,'\n');
    }
    
    int main() {
    	read(n);
    	p[0] = 1;
    	rep(i, 1, n) {
    		while((s = gt()) < 'a' || s > 'z');
    		p[i] = p[i - 1] * base;
    		H[i] = H[i - 1] * base + s;
    	}
    	EulerSieve(n);
    	read(q);
    	while(q--) {
    		read(x);
    		read(y);
    		solve(x, y);
    	}
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15574552.html

  • 相关阅读:
    springboot自定义jar打包不能导入到项目中
    ajax上传文件+传json数据
    cooladmin vitevue3 打包部署 nginx代理设置
    istio 安装
    logging
    orm 多对多
    shell 多线程
    舒服的jenkins子节点
    phpfpm coredump
    drf 自定义异常
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15574552.html
Copyright © 2011-2022 走看看