您的位置:首页 > 其它

[POI2012]A Horrible Poem

2018-03-13 18:27 225 查看

题目大意:
  给定一个长度为$n(n\leq5\times10^5)$的字符串$S$,$q(q\leq2\times10^6)$组询问,每次询问子串$S_{[l_i,r_i]}$最小循环节。

思路:
  若$i$是循环节,则最小循环节一定是$i$的因数。因此可以线性筛预处理出$1\sim n$每个数的最大质因数,然后根据情况用当前因数去除当前答案,不断枚举出其它的一些可能的答案即可。

#include<cstdio>
#include<cctype>
typedef unsigned long long uint64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=500001,BASE=31;
char s
;
bool vis
;
uint64 pow
,h
;
int n,div
,p
;
inline void sieve() {
for(register int i=2;i<=n;i++) {
if(!vis[i]) {
div[i]=p[++p[0]]=i;
}
for(register int j=1;j<=p[0]&&p[j]*i<=n;j++) {
vis[i*p[j]]=true;
div[i*p[j]]=p[j];
if(i%p[j]==0) break;
}
}
}
inline uint64 hash(const int &l,const int &r) {
return h[r]-h[l-1]*pow[r-l+1];
}
int main() {
n=getint();
scanf("%s",s);
for(register int i=pow[0]=1;i<=n;i++) {
pow[i]=pow[i-1]*BASE;
h[i]=h[i-1]*BASE+s[i-1]-'a';
}
sieve();
for(register int i=getint();i;i--) {
const int l=getint(),r=getint();
int ans=r-l+1;
for(register int i=ans;i!=1;) {
int j=div[i];
while(ans%j==0&&hash(l,r-ans/j)==hash(l+ans/j,r)) ans/=j;
while(i%j==0) i/=j;
}
printf("%d\n",ans);
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: