题目大意

给出一个由小写英文字母组成的字符串 S,再给出 q 个询问,要求回答 S 某个子串的最短循环节。

如果字符串 B 是字符串 A 的循环节,那么 A 可以由 B 重复若干次得到。

输入格式

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

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

第三行一个正整数 q ,表示询问个数。

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

输出格式

依次输出 q 行正整数,第 i 行的正整数对应第 i 个询问的答案。

输入样例

8

aaabcabc

3

1 3

3 8

4 8

输出样例

1

3

5

数据范围

1≤a≤b≤n≤5×10^5​​ , q≤2×10^5。

题解

容易想到,对于每一个子串,我们要枚举其循环节,而循环节的长度一定是子串长度的因子。所以关键是枚举出对于每一个数的所有因子。

对于每个子串,用$O(\sqrt{n}) $的朴素枚举显然会TLE。所以我们要换一种枚举方法。

我们先欧拉筛求出$1... n$的所有质数,根据欧拉筛的枚举顺序,我们也可以顺便求出任意一个数$i$的最小质因子$mp[i]$。

枚举出这个有什么用呢?其实我们可以根据这个求出任意长度$len$的所有质因子。

我们用$t[i]$表示$len$的第$i$个质因子,我们不断记录$mp[len]$,然后让$len = \frac{len}{mp[len]}$,直到$len = 1$为止。此时我们就可以得到$len$的$cnt$个质因子$t[1...cnt]$,且有$t[i] \leqslant t[i + 1]$。

我们设最短循环节的长度为$len$。最开始我们然后$len$等于子串长度。

然后我们从$t[1]$开始枚举$t[i]$,我们先让$len = \frac{len}{t[i]}$,然后判断此时的$len$是否是循环节长度,如果不是,则再让$len$乘回$t[i]$。判断完后继续枚举$t[i]$即可。这样我们就可以不断得到越来越小的循环节长度,直到得到答案。

#include <iostream>
#include <cstdio>
#include <cctype> #define MAX_N (500000 + 5) #define SIZE (1 << 21) #define Getchar() (pr1 == pr2 && (pr2 = (pr1 = fr) + fread(fr, 1, SIZE, stdin), pr1 == pr2) ? EOF : *pr1++)
#define Putchar(ch) (pw < SIZE ? fw[pw++] = (ch) : (fwrite(fw, 1, SIZE, stdout), fw[(pw = 0)++] = (ch))) using namespace std; char fr[SIZE], * pr1 = fr, * pr2 = fr;
char fw[SIZE];
int pw; int Read()
{
int res = , sign = ;
char ch = Getchar();
while(!isdigit(ch))
{
if(ch == '-') sign = -;
ch = Getchar();
}
while(isdigit(ch))
{
res = res * + ch - '';
ch = Getchar();
}
return res * sign;
} void Write(int val)
{
char a[];
int len = ;
if(val < )
{
val = -val;
Putchar('-');
}
do
{
a[++len] = val % + '';
val /= ;
}
while(val);
while(len)
{
Putchar(a[len--]);
}
return;
} typedef unsigned long long ull;
typedef const unsigned long long cull;
int n;
char s[MAX_N];
cull b = ;
ull h[MAX_N], pb[MAX_N];
int p[MAX_N], mp[MAX_N], tot; void Euler()
{
for(register int i = ; i <= n; ++i)
{
if(!mp[i]) p[++tot] = mp[i] = i;
for(register int j = ; i * p[j] <= n; ++j)
{
mp[i * p[j]] = p[j];
if(!(i % p[j])) break;
}
}
return;
} void Hash()
{
pb[] = ;
for(register int i = ; i <= n; ++i)
{
h[i] = h[i - ] * b + s[i] - 'a' + ;
pb[i] = pb[i - ] * b;
}
return;
} ull Value(int lt, int rt)
{
return h[rt] - h[lt - ] * pb[rt - lt + ];
} int main()
{
n = Read();
for(register int i = ; i <= n; ++i)
{
s[i] = Getchar();
}
Euler();
Hash();
int q, lt, rt;
q = Read();
int t[MAX_N], cnt, len;
while(q--)
{
lt = Read();
rt = Read();
len = rt - lt + ;
cnt = ;
while(len > )
{
t[++cnt] = mp[len];
len /= mp[len];
}
len = rt - lt + ;
for(register int i = ; i <= cnt; ++i)
{
len /= t[i];
if(Value(lt, rt - len) != Value(lt + len, rt)) len *= t[i];
}
Write(len);
Putchar('\n');
}
fwrite(fw, , pw, stdout);
return ;
}

参考程序

【题解】A Horrible Poem的更多相关文章

  1. P3538 [POI2012]OKR-A Horrible Poem

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

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

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

  3. 2795: [Poi2012]A Horrible Poem

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

  4. [BZOJ2795][Poi2012]A Horrible Poem

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

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

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

  6. #10038.A Horrible Poem

    #10038.A Horrible Poem 题目传送门 思路解析 既然这道题目在hash板块里,那么自然就可以想到用hash做这道题目. 首先我们可以用hash数组存储字符串的前缀的hash值. 因 ...

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

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

  8. 洛谷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 ...

  9. 【hash】A Horrible Poem

    [题目链接] # 10038. 「一本通 2.1 练习 4」A Horrible Poem [参考博客] A Horrible Poem (字符串hash+数论) [题目描述] 给出一个由小写英文字母 ...

  10. A Horrible Poem (字符串hash+数论)

    # 10038. 「一本通 2.1 练习 4」A Horrible Poem [题目描述] 给出一个由小写英文字母组成的字符串 $S$,再给出 $q$ 个询问,要求回答 $S$ 某个子串的最短循环节. ...

随机推荐

  1. 【TWRP】使用adb sideload线刷ROM的方法

    本教程详细介绍 手机刷三方ROM 之前需要安装的 TWRP 这个神器工具 楼主的手机是小米,所以此教程以小米手机为例.其他手机原理类似 第一步,解锁引导程序 访问小米的官方解锁网站并申请解锁权限. 等 ...

  2. ES2015箭头函数与普通函数对比理解

    直接返回表达式 var odds = evens.map(v => v + 1); var nums = evens.map((v, i) => v + i); var odds = ev ...

  3. Python-编码这趟浑水

    最近听Alex讲到python编码,还特意用博客讲解,觉得问题严重了,于是翻看各种博客,先简单的对编码错误做一个总结,其他的后续慢慢补上,还得上班.还得学习.还得写博客?感觉有点吃不消了.各位大神不喜 ...

  4. 基本的bash shell

    一.linux文件系统 linux文件系统结构是从Unix文件结构演进过来的.在linux文件系统中,通用的目录名用于表示一些常见的功能.如下表列出一些较为常见的Linux顶层虚拟目录名及其内容. / ...

  5. android5.1修改系统默认音量

    在做定制需求的时候,需要修改系统通知的声音,将其禁用掉,避免第三方应用发送通知时,声音很大,吓着用户.索性就把通知声音关掉.下面就说说关闭声音的几种方法,以及修改系统默认声音的方法. 1. 直接修改系 ...

  6. 五 shell 变量与字符串操作

    特点:1 shell变量没有数据类型的区分 2 Shell 把任何存储在变量中的值,皆视为以字符组成的“字符串”.    3  设定的变量值只在当前shell环境中有作用    4   不能以数字开头 ...

  7. python常用函数 B

    B bin(int) 将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法__index__()并且返回值为integer. 例子:

  8. Swagger添加文件上传测试

    先上对比图 图一无法选择文件,图二可以选择文件 图一 图二 添加过滤器 public class SwaggerFileUploadFilter : IOperationFilter { /// &l ...

  9. 「校内训练 2019-04-23」越野赛车问题 动态dp+树的直径

    题目传送门 http://192.168.21.187/problem/1236 http://47.100.137.146/problem/1236 题解 题目中要求的显然是那个状态下的直径嘛. 所 ...

  10. 洛谷4843 BZOJ2502 清理雪道

    有源汇有上下界的最小可行流. YY一下建图应该很好搞吧(? 就是对于每个雪道都是[1,inf]然后源点到所有点都是[0,inf]所有点到汇点都是[0,inf] 这样的话跑一个有源汇上下界最小可行流就可 ...