題意:詢問字符串指定區間循環節個數。
解法:有循環節長度a的字符串s[x,y]的性質:s[x,y-a]==s[x+a,y]由此寫一個雙hash就行了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 1100000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define PROB "password"
#define _a 29
#define _b 131
#define mod 1000000007
typedef unsigned long long qword;
inline int nextInt()
{
char ch;
int x=;
bool flag=false;
do
ch=getchar(),flag=(ch=='-')?true:flag;
while(ch<''||ch>'');
do x=x*+ch-'';
while (ch=getchar(),ch<='' && ch>='');
return x*(flag?-:);
} int n,m;
char str[MAXN];
pair<qword,qword> hs[MAXN];
bool pflag[MAXN];
int prime[MAXN],topp=-;
qword pow_a[MAXN];
qword pow_b[MAXN];
void init()
{
int i,j;
for (i=;i*i<MAXN;i++)
{
if (!pflag[i])
prime[++topp]=i;
for (j=;j<=topp && i*prime[j]<MAXN;j++)
{
pflag[i*prime[j]]=true;
if (i%prime[j]==)break;
}
}
pow_a[]=;
pow_b[]=;
for (i=;i<MAXN;i++)
pow_a[i]=pow_a[i-]*_a%mod,
pow_b[i]=pow_b[i-]*_b;
}
pair<qword,qword> hash(int x,int y)
{
pair<qword,qword> ret;
ret.first=((hs[x].first+mod-hs[y+].first*pow_a[(y+)-x]%mod)%mod+mod)%mod;/*Attention*/
ret.second=hs[x].second-hs[y+].second*pow_b[(y+)-x];
return ret;
}
int check(int x,int y)
{
int ret=;
int len=(y-x+);
int lo=len;
int a,i;
for (i=;i<=topp && prime[i]*prime[i]<=len;i++)
{
if (len%prime[i]==)
{
a=;
while (len%prime[i]==)
{
len/=prime[i];
a*=prime[i];
if (hash(x,y-lo/a)==hash(x+lo/a,y))
{
ret*=prime[i];
}
}
}
}
if (len>)
{
a=len;
if (hash(x,y-lo/a)==hash(x+lo/a,y))
{
ret*=a;
}
}
return ret;
} int main()
{
freopen(PROB".in","r",stdin);
//freopen(PROB".out","w",stdout);
int i,j,k;
int x,y,z;
int ans;
init();
scanf("%d\n",&n);
fgets(str,sizeof(str),stdin);
hs[n]=make_pair(,);
for (i=n-;i>=;i--)
{
hs[i].first=hs[i+].first*_a%mod+str[i]-'a'+;
hs[i].second=hs[i+].second*_b+str[i]-'a'+;
}
// pr3=hash(5,5);
scanf("%d",&m);
for (i=;i<m;i++)
{
scanf("%d%d",&x,&y);
x--;y--;
printf("%d\n",(y-x+)/check(x,y));
}
return ;
}