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

Sample Output

1
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
*/

 

posted @ 2018-05-20 08:39  fcwww  阅读(258)  评论(0编辑  收藏  举报