题面:洛谷

题解:

  首先我们需要知道一个性质,串s的最小循环节 = len - next[len].其中next[len]表示串s的一个最长长度使得s[1] ~ s[next[len]] == s[len - next[len] + 1] ~ s[len](详细定义参见KMP)

  至于为什么是成立的可以画图推一下,这个应该是比较常见的性质。

  

  可能画的有点丑。。。

  图中每个绿色方块所代表的串都是相同的,因为第一个绿块显然与下面那块相同,而根据next的定义,它也与第二行第二个绿块相同……以此类推,可以一直递推下去,直到推完整个数组。

  

  对于一个长度为len的串s而言,设它的最小循环节长度为l.

  若$len = p_{1}^{k_{1}} \cdot p_{2}^{k_{2}} \cdot p_{3}^{k_{3}}...p_{t}^{k_{t}}$

  则$len = p_{1}^{a_{1}} \cdot p_{2}^{a_{2}} \cdot p_{3}^{a_{3}}...p_{t}^{a_{t}}$其中$a_{i} \le k_{i}$.

  首先一个串的最大循环节长度肯定= len;

  而这个循环节之所以可以变小,是因为这个最大循环节是由很多个最短循环节组成。我们假设最短循环节为X,这这个串可以表示为XXXXXXX(若干个X)

  假设X有b个。那么我们可以每次对b缩减一个b的因子,最后使得b变为1,即使b不断除一个数。

  例如一个串s一开始可以被表示为XXXXXXXX(8个X),即b = 8

  这个时候我们枚举到一个2,于是我们判断原串是否可以被XXXX + XXXX凑出,如果可以,那么b /= 2.

  然后我们判断原串是否可以被XX + XX + XX + XX凑出,如果可以,那么b /= 2.

  依次类推,直到已经没有更小的循环节可以凑出原串位置。

  其中2是b的某个质因子。

  因为b的最大值为len(即循环节为1),所以我们一开始先从len开始,不断枚举len的质因子,看能否消去这个因子,最后剩下的数就是答案。

  判断一个长度是否可以成立,可以用hash判断图中红色部分是否相等

  

  其中绿块长度为x。

  原理就是一开始解释过的KMP求最小循环节。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 501000
#define p1 1000000007
#define p2 998244353
#define base 26
#define LL long long int n, m, tot, top;
int hash1[AC], hash2[AC], pw1[AC], pw2[AC];
int pri[AC], last[AC], q[AC];
char s[AC];
bool z[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} void get()//欧拉筛
{
for(R i = ; i <= n; i ++)
{
if(!z[i]) pri[++ tot] = i, last[i] = i;
for(R j = ; j <= tot; j ++)
{
int now = pri[j];
if(now * i > n) break;
z[now * i] = true, last[now * i] = now;
if(!(i % now)) break;
}
}
} void pre()
{
n = read();
scanf("%s", s + );
} void build()//求前缀hash值
{
pw1[] = pw2[] = ;
for(R i = ; i <= n; i ++)
{
hash1[i] = (1ll * hash1[i - ] * base + s[i] - 'a' + ) % p1;
hash2[i] = (1ll * hash2[i - ] * base + s[i] - 'a' + ) % p2;
pw1[i] = 1ll * pw1[i - ] * base % p1;//存下base的i次方
pw2[i] = 1ll * pw2[i - ] * base % p2;
}
} LL cal(int l, int r, bool w){
if(!w) return ((1ll * hash1[r] - 1ll * hash1[l - ] * pw1[r - l + ] % p1) + p1) % p1;
else return ((hash2[r] - 1ll * hash2[l - ] * pw2[r - l + ] % p2) + p2) % p2;
} bool check(int l, int r, int x){//测试区间[l, r]的循环结是否可能为x
return (cal(l + x, r, ) == cal(l, r - x, )) && (cal(l + x, r, ) == cal(l, r - x, ));
} void work()
{
m = read();
for(R i = ; i <= m; i ++)
{
int l = read(), r = read(), x = r - l + ;
top = ;
while(x != ) q[++ top] = last[x], x /= last[x];
x = r - l + ;
for(R i = ; i <= top; i ++)
if(check(l, r, x / q[i])) x /= q[i];
printf("%d\n", x);
}
} int main()
{
// freopen("in.in", "r", stdin);
pre();
get();//处理last数组
build();//构建hash数组
work();
// fclose(stdin);
return ;
}

  

[POI2012]OKR-A Horrible Poem hash的更多相关文章

  1. BZOJ 2795: [Poi2012]A Horrible Poem( hash )

    ...字符串hash. 假如长度x是一个循环节, 那么对于任意n(x | n)也是一个循环节. 设当前询问区间[l, r]长度为len = ∏piai, 最终答案ans = ∏piai' ,我们只需枚 ...

  2. bzoj 2795 [Poi2012]A Horrible Poem hash+数论

    2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 640  Solved: 322[Subm ...

  3. 【BZOJ2795】[Poi2012]A Horrible Poem hash

    [BZOJ2795][Poi2012]A Horrible Poem Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串 ...

  4. 【bzoj2795】[Poi2012]A Horrible Poem Hash+分解质因数

    题目描述 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. 输入 第一行一个正整数n (n<= ...

  5. bzoj 2795 [Poi2012]A Horrible Poem hash+线性筛

    题目大意 bzoj 2795 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节. 如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. n<=500 ...

  6. BZOJ2795&2890&3647[Poi2012]A Horrible Poem——hash

    题目描述 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. 输入 第一行一个正整数n (n<= ...

  7. 【bzoj2795】【Poi2012】A Horrible Poem

    题解: 询问区间的整循环节 设区间长度为$n$ 如果有循环节长为$x$和$y$,那由斐蜀定理得$gcd(x,y)$也一定为一个循环节: 假设最小的循环节长为$mn$,那么对于任何循环节长$x$,一定$ ...

  8. P3538 [POI2012]OKR-A Horrible Poem

    P3538 [POI2012]OKR-A Horrible Poem hash+线性筛 题解 <----这篇写的不错(其实是我懒得码字了qwq) UVA10298 Power Strings 的 ...

  9. 洛谷P3538 [POI2012]OKR-A Horrible Poem [字符串hash]

    题目传送门 A Horrible Poem 题目描述 Bytie boy has to learn a fragment of a certain poem by heart. The poem, f ...

随机推荐

  1. Jlink v8仿真器在64位系统上刷固件

    1. 安装软件sam-ba_2.16.exe.本次主要是Jlink v8在64位系统下面的刷固件方法. 2. J-link通过USB连接至电脑,短接PCB上标号为ERASE的焊盘5秒,断开ERASE两 ...

  2. Unity CombineTexture

    public Texture2D CombineTexture(Texture2D background, Texture2D top) { int width = background.width; ...

  3. linux菜鸟笔记

    linux目录的子目录复制 cp -r 要复制的目录+新的目录 cp -r a test 意思就是将a的子目录及文件复制到新的目录test下面 zt@ubuntu:~/Desktop$ mkdir - ...

  4. perf + 火焰图用法 小结

    要对新服务做性能测试,分析代码热点,初识perf,做下总结 perf + 火焰图用法 perf简介 Perf (Performance Event), Linux 系统原生提供的性能分析工具, 会返回 ...

  5. Unity3D之AR开发(二)

    上一篇给大家介绍了高通AR的使用,接下来给大家分享一下EasyAR EasyAR引擎简介 EasyAR是做好用的且免费的增强现实(Augmented Reality)引擎,EasyAR为Unity开发 ...

  6. JavaScript(js)处理的HTML事件、键盘事件、鼠标事件

    示例代码: HTML文件: <!DOCTYPE html><html lang="en"><head> <meta charset=&qu ...

  7. ES数据备份到HDFS

    1.准备好HDFS(这里我是本机测试) 2.es 安装repository-hdfs插件 (如es为多节点需在每个节点都安装插件) elasticsearch-plugin install repos ...

  8. MSCOCO - pycocoDemo 学习版

    Reference: https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoDemo.ipynb https://git ...

  9. 雅虎工程师提供的CSS初始化示例代码

    body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,b ...

  10. redis 常用命令 结合php

    这篇文章主要介绍了30个php操作redis常用方法代码例子,本文其实不止30个方法,可以操作string类型.list类型和set类型的数据,需要的朋友可以参考下     redis的操作很多的,以 ...