题面:洛谷

题解:

  首先我们需要知道一个性质,串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. 使用T4模板报错:“正在编译转换;当前上下文中不存在名称Host”

             用T4模板生成多个文件的实体时,有一句代码是这样的 string curPath = Path.GetDirectoryName(Host.TemplateFile);       ...

  2. 阿里云Ubuntu 14.04 + Nginx + .net core + MySql

    前段时间帮朋友写了一个网站,现在做一个记录. .Net Core 安装: curl https://packages.microsoft.com/keys/microsoft.asc | gpg -- ...

  3. 身份证扫描识别/身份证OCR识别的正确姿势,你get到了吗?

    自从国家规定电信实名制之后,实名制已经推广到各个领域:办理通信业务需要实名制.银行开户需要实名制.移动支付需要实名制,就连注册个自媒体账户都需要实名制. 而实名制的背后,就是身份证信息的采集和录入验证 ...

  4. 180719-Quick-Task 动态脚本支持框架之使用介绍篇

    文章链接:https://liuyueyi.github.io/hexblog/2018/07/19/180719-Quick-Task-动态脚本支持框架之使用介绍篇/ Quick-Task 动态脚本 ...

  5. 【转】glumer Appium + Python环境搭建(移动端自动化)

    最近整理了一下自动化的东西,好久没搭建环境又踩了不少坑,appium的环境搭建比较繁琐,好多同行估计都在环境上被卡死了.分享一下~~ 一.安装JDK,配置JDK环境    百度搜索下载就行,这里分享一 ...

  6. TW实习日记:第八天

    今天早上主要是接着做昨天的微信端网页预览附件,听同事说当打包代码放入服务器上后,就不存在跨域问题了,也就懒得自己写接口了,那么就希望自己能一次过吧...结果写着写着,发现开发文档中关于预览文件的方法, ...

  7. 论文笔记:Visualizing and Understanding Convolutional Networks

    2014 ECCV 纽约大学 Matthew D. Zeiler, Rob Fergus 简单介绍(What) 提出了一种可视化的技巧,能够看到CNN中间层的特征功能和分类操作. 通过对这些可视化信息 ...

  8. oracle时间转换查询

    查询oracle 数据库时要查询某一字段的最大时间或者最小时间,因为oracle的时间点 精确到毫秒 甚至更高精度级别 根据字段来转换成对应的时间格式: SELECT TO_CHAR(MAX(crea ...

  9. Python Pygame (2) 事件

    程序在运行期间会产生许许多多的事件,事件随时可能发生(如移动鼠标,点击鼠标,敲击键盘按键),Pygame的做法是将所有的事件都放到事件队列里,通过for循环语句迭代取出每一条事件,然后处理关注的事件即 ...

  10. Tempter of the Bone HDU 1010(DFS+剪枝)

    Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. However, ...