[BZOJ2795] [Poi2012] [字符串hash] A Horrible Poem

来源:互联网 发布:如何优化标题 编辑:程序博客网 时间:2024/05/20 12:22

一个字符串的最小周期等于这个字符串的长度-border的长度
那么如果x是字符串的周期,[l,r-x]一定和[l+x,r]相等。
然后发现x一定是字符串的长度的约数,就枚举一下约数,字符串hash判一判就可以了

线性筛预处理一下可以O(log)质因数分解

#include <cstdio>#include <iostream>#include <algorithm>#define N 500010#define base 139using namespace std;typedef unsigned long long ll;int n,q;int p[N],divi[N];char a[N];ll hash[N],power[N];inline void Pre(){  for(int i=2;i<=N-10;i++){    if(!p[i]) p[++*p]=i,divi[i]=i;    for(int j=1;j<=*p&&1ll*p[j]*i<=N-10;j++){      p[p[j]*i]=1; divi[p[j]*i]=p[j];      if(i%p[j]==0) break;    }  }}inline bool check(int l,int r,int L,int R){    ll h1=hash[r]-hash[l-1]*power[r-l+1],h2=hash[R]-hash[L-1]*power[R-L+1];    return h1==h2;}inline int query(int l,int r){  int len=r-l+1,ret=r-l+1;  while(len^1){    int cur=divi[len];    while(ret%cur==0&&check(l,r-ret/cur,l+ret/cur,r)) ret/=cur;    while(len%cur==0) len/=cur;  }  return ret;}int main(){    //freopen("1.in","r",stdin);    //freopen("1.out","w",stdout);  scanf("%d%s%d",&n,a+1,&q);  power[0]=1;  for(int i=1;i<=n;i++)    hash[i]=hash[i-1]*base+a[i]-'a'+1,power[i]=power[i-1]*base;  Pre();  while(q--){    int l,r;    scanf("%d%d",&l,&r);    printf("%d\n",query(l,r));  }  return 0;}
原创粉丝点击