2795: [Poi2012]A Horrible Poem hash

来源:互联网 发布:流畅的python 编辑:程序博客网 时间:2024/06/07 06:50

求最小循环节,可以枚举最小循环节的长度len,然后判断[a..blen],[a+len,b]的hash值是否相等。然后一开始写的O(NN)的发现TLE了。然后我们发现,如果len是循环节,则len×p也是循环节(lenp|(ba+1)),于是可以分解质因数,每次删去质因数就好了。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define base 2333#define N 500005#define inf 1e9using namespace std;int n;char s[N];int mn[N],prime[N];bool flag[N];unsigned long long T[N],hash[N];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline unsigned long long gethash(int l,int r){    return hash[r]-hash[l-1]*T[r-l+1];}inline bool check(int st,int en,int len){    int total=en-st+1;    if (gethash(st,st+total-len-1)==gethash(st+len,en)) return true;    return false;}inline void pre(){    for (int i=2;i<=n;i++)    {        if (!flag[i]) prime[++prime[0]]=i,mn[i]=i;        for (int j=1;j<=prime[0]&&i*prime[j]<=n;j++)        {            flag[i*prime[j]]=1;            mn[i*prime[j]]=prime[j];            if (i%prime[j]==0) break;        }    }}int main(){    n=read();    pre();    scanf("%s",s+1);    T[0]=1;    for (int i=1;i<=n;i++)        T[i]=T[i-1]*base;    for (int i=1;i<=n;i++)        hash[i]=hash[i-1]*base+s[i]-'a'+1;    int query=read();    while (query--)    {        int a=read(),b=read();        int len=b-a+1;        int x=len;        while (x>1)        {            int y=mn[x];            while (len%y==0&&check(a,b,len/y)) len/=y;            while (x%y==0) x/=y;        }        printf("%d\n",len);    }    return 0;}
0 0