BZOJ_2795_[Poi2012]A Horrible Poem_hash+暴力
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
我们现在要求[L,R]的最短循环节,假设长度为x。
那么满足[L+x,R]和[L,R-x]两个子串是相等的,这一步可以用hash解决。
随机询问n次某个数的约数个数这个是期望$O(nln)$的,上限是$O(n\sqrt n)$。
所以我们先把每个数的约数处理出来,存到vector中,这一步也是$O(nln)$的。
询问时暴力枚举约数即可。
然后hash用unsigned int自然溢出,卡一卡就过了。
代码:
// luogu-judger-enable-o2 #include <stdio.h> #include <string.h> #include <algorithm> #include <vector> using namespace std; #define N 500050 #define RR register __attribute__((optimize("-O2")))inline char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } __attribute__((optimize("-O2")))inline int rd() { RR int x=0;RR char c=nc(); while(c<'0'||c>'9') c=nc(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=nc(); return x; } __attribute__((optimize("-O2")))inline int rc() { RR char c=nc(); while(c<'a'||c>'z') c=nc(); return (int)c; } typedef unsigned int ll; int n,m; int s[N]; ll h[N],mi[N],base=19260817; vector<int>q[N]; __attribute__((optimize("-O2")))inline ll get_hash(int l,int r) { return h[r]-h[l-1]*mi[r-l+1]; } __attribute__((optimize("-O2")))inline int solve(int l,int r) { int len=r-l+1,i; int siz=q[len].size(); for(i=0;i<siz;i++) { int x=q[len][i]; if(get_hash(l+x,r)==get_hash(l,r-x)) return x; } } char pbuf[10000000] , *pp = pbuf; inline void write(int x) { static int sta[20]; RR int top = 0; if(!x)sta[++top]=0; while(x) sta[++top] = x % 10 , x /= 10; while(top) *pp ++ = sta[top -- ] ^ '0'; } __attribute__((optimize("-O2")))int main() { RR int i,x,y,j; n=rd(); for(i=1;i<=n;i++) s[i]=rc(); m=rd(); for(mi[0]=1,i=1;i<=n;i++) { h[i]=h[i-1]*base+s[i]; mi[i]=mi[i-1]*base; } for(i=1;i<=n;i++) { for(j=i;j<=n;j+=i) { q[j].push_back(i); } } while(m--) { x=rd(); y=rd(); write(solve(x,y));*pp ++ ='\n'; } fwrite(pbuf , 1 , pp - pbuf , stdout); } /* 8 aaabcabc 3 1 3 3 8 4 8 */