P3538 [POI2012]OKR-A Horrible Poem

P3538 [POI2012]OKR-A Horrible Poem

Describe:

第一行一个正整数 n(n500000),表示 S 的长度。

第二行n个小写英文字母,表示字符串 S

第三行一个正整数 q(q2000000),表示询问次数。

下面q行每行两个正整数a,b(1abn),表示询问字符串 S[ab] 的最短循环节长度。

Sol:

显然的,最短循环长度的 k (kZ) 倍一定是 ba+1,也就是说循环长度 len 一定是长度的因子。

再就因为是循环的,所以从 ll+len1 rlen+1r 应该是一样的。

那么我们就可以用哈希做到 O(1)

注意的是,枚举因子要从大到小枚举,另外,我们可以利用线性筛是利用枚举最小质因子的方式来记录下每个数的最小质因子,然后除一下找到最大因子,以此类推。

Code:

/*
Knowledge : Rubbish Algorithm
Work by :Gym_nastics
Time : O(AC)
*/
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int Mod=1e9+7;
const int Base=131;
const int N=1e6+6;

int read() {
    int x=0,f=0;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) f|=(ch=='-');
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch&15);
    return f?-x:x;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+48);
}

int Prime[N],M[N],cnt,h[N],P[N];bool vis[N];
void prepare(){
    for(int i=2;i<=1e6;i++){
        if(!vis[i]) Prime[++cnt]=i,M[i]=i;
        for(int j=1;j<=cnt&&i*Prime[j]<=1e6;j++){
            vis[i*Prime[j]]=1;M[i*Prime[j]]=Prime[j];
            if(!(i%Prime[j])) break;
        }
    }
}

char ch[N];
signed main() {
   int l=read();cin>>ch+1;int Q=read();P[0]=1;prepare();
   for(int i=1;i<=l;i++) h[i]=h[i-1]*Base+ch[i],P[i]=P[i-1]*Base;
   while(Q--){
       int l=read(),r=read(),len,ans;
       ans=len=r-l+1;while(len^1){
       int k=ans/M[len];len/=M[len];
       if(!(h[r-k]-h[l-1]*P[r-k-l+1]^h[r]-h[l-1+k]*P[r-k-l+1])) ans=k;
       }print(ans);putchar('\n');
   }
   return 0;
}

本文作者:Gym_nastics

本文链接:https://www.cnblogs.com/BlackDan/p/15999728.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Gym_nastics  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起