bzoj 2795 [Poi2012]A Horrible Poem hash+数论
2795: [Poi2012]A Horrible Poem
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 640 Solved: 322
[Submit][Status][Discuss]
Description
给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节。
如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到。
Input
第一行一个正整数n (n<=500,000),表示S的长度。
第二行n个小写英文字母,表示字符串S。
第三行一个正整数q (q<=2,000,000),表示询问个数。
下面q行每行两个正整数a,b (1<=a<=b<=n),表示询问字符串S[a..b]的最短循环节长度。
Output
依次输出q行正整数,第i行的正整数对应第i个询问的答案。
Sample Input
8
aaabcabc
3
1 3
3 8
4 8
aaabcabc
3
1 3
3 8
4 8
Sample Output
1
3
5
3
5
%%https://blog.csdn.net/ww140142/article/details/48260615
1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 #include<algorithm> 5 #include<iostream> 6 #include<vector> 7 8 #define G 29 9 #define N 500007 10 #define mod 1000000007 11 #define ll long long 12 13 #define Wb putchar(' ') 14 #define We putchar('\n') 15 #define rg register int 16 using namespace std; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 21 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 22 return x*f; 23 } 24 inline void write(int x) 25 { 26 if(x<0) putchar('-'),x=-x; 27 if (x==0) putchar(48); 28 int num=0;char c[15]; 29 while(x) c[++num]=(x%10)+48,x/=10; 30 while(num) putchar(c[num--]); 31 } 32 33 int n,Q; 34 char ch[N]; 35 ll bin[N],hash[N]; 36 bool flag[N]; 37 vector<int>ve[N]; 38 39 void init_prime() 40 { 41 for (rg i=2;i<=n;i++) 42 if (!flag[i]) 43 { 44 rg x=i; 45 while(x<=n) 46 { 47 int z=x; 48 while(z%i==0) ve[x].push_back(i),z/=i; 49 flag[x]=true; 50 x+=i; 51 } 52 } 53 } 54 bool judge(int x,int l,int r) 55 { 56 ll res1=hash[r-x]-(hash[l-1]*bin[(r-x)-l+1])%mod; 57 ll res2=hash[r]-(hash[l+x-1]*bin[(r-x)-l+1])%mod; 58 res1=(res1%mod+mod)%mod,res2=(res2%mod+mod)%mod; 59 return res1==res2; 60 } 61 int main() 62 { 63 n=read(),scanf("%s",ch+1),bin[0]=1,init_prime(); 64 for (int i=1;i<=n;i++) 65 hash[i]=(hash[i-1]*G+ch[i]-'a')%mod,bin[i]=(bin[i-1]*G)%mod; 66 Q=read(); 67 while(Q--) 68 { 69 int l=read(),r=read(),num=r-l+1,ans=num; 70 if (num==1) write(1),We; 71 else 72 { 73 for (rg i=0;i<ve[num].size();i++) 74 if (judge(ans/ve[num][i],l,r)) ans/=ve[num][i]; 75 write(ans),We; 76 } 77 } 78 }