#10038.A Horrible Poem

题目传送门

思路解析

既然这道题目在hash板块里,那么自然就可以想到用hash做这道题目。

首先我们可以用hash数组存储字符串的前缀的hash值。

因为我们需要找到S[a..b] 的最短循环节长度,所以我们可以枚举循环节长度 i 。

由于循环要遍历完整个字串。所以设字串长度为 \(len\) ,就有:

if(len%i)continue;

即i为\(len\)的因数。

关于判断循环节,我们最先想到的就是将一个长度为i字串不断往后对比,直到遍历完长度为\(len\)的字串。

如果此时还是没有出现不匹配的情况,那么就可以输出答案i了。

while(Q--){
int a=read(),b=read(),len=b-a+1;
for(int i=1;i<=len;++i){
if(len%i)continue;
bool flag=1;ull cmp=f[a+i-1]-f[a-1]*p[i];
for(int j=a+i*2-1;j<=b;j+=i)
if(f[j]-f[j-i]*p[i]!=cmp){flag=0;break;}
if(flag){write(i);putchar('\n');break;}
}
}

但是这样的做法复杂度为\(O(qn \sqrt n )\) ,显然会超时。(废话)

仔细一想可以发现我们在判断循环节的时候我们浪费了一部分时间,那有没有更快的判断循环节的方法呢?

(显然是有的)

if(H(a,b-i)==H(a+i,b)){write(i);putchar('\n');break;}

这是H函数,表示l~r间的值。

ull H(int l,int r){return f[r]-f[l-1]*p[r-l+1];}

这种做法(当然不是作者独立想出来的啦!)可以将判断循环节的复杂度降到\(O(1)\)。

让我们来理解一下这种做法:

前一个串中的每一个单位都和后面应该单位比较,一但出现有一个不相等就会判为不循环。

于是代码就变成这样:

while(Q--){
int a=read(),b=read(),len=b-a+1;
for(int i=1;i<=len;++i){
if(len%i)continue;
if(H(a,b-i)==H(a+i,b)){write(i);putchar('\n');break;}
}
}

(哈哈哈变短了!)

这样复杂度还是\(O(qn)\)会超时。

这时我们想我们枚举了许多不必要的i,所以只需要把一些不必要的i去掉就可以了。

上代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=500005,base=53;
int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x;
}
char get(){
char c=getchar();
while(c<'a'||c>'z')c=getchar();
return c;
}
void write(int x){if(x/10)write(x/10);putchar(x%10+'0');}
ull f[N],p[N];
int n,ss[N],nxt[N],tmp[N],next[N],tot;
bool vis[N];
char a[N];
ull H(int l,int r){return f[r]-f[l-1]*p[r-l+1];}
int main(){
p[0]=1;for(int i=1;i<=N;++i)p[i]=p[i-1]*base;
n=read();f[0]=1;
for(int i=1;i<=n;++i){
char ch=get();
f[i]=f[i-1]*base+ch;
}
for(int i=2;i<=n;++i){//欧拉筛
if(!vis[i]){ss[++tot]=i;next[i]=i;}
for(int j=1;j<=tot&&(ull)ss[j]*i<=n;++j){
vis[ss[j]*i]=1;
next[ss[j]*i]=ss[j];//找出最小的质因数
if(i%ss[j]==0)break;
}
}
int Q=read();
while(Q--){
int a=read(),b=read(),len=b-a+1,sum=0;
while(len!=1){
tmp[++sum]=next[len];//tmp数组储存len的所有质因数
len/=next[len];//此时next数组就可以做到检索出len的所有质因数
}
len=b-a+1;
for(int j=1;j<=sum;++j){
int k=len/tmp[j];
//判断长度为k的字串是否能在长度为len的循环中构成循环(一开始原串len视为长度为len的循环)
//因为在len中可以构成循环就代表着可以在a~b中构成循环
if(H(a,b-k)==H(a+k,b))len=k;//当字串k构成循环时就可以在字串k中寻找循环节
}
write(len);putchar('\n');
}
return 0;
}

#10038.A Horrible Poem的更多相关文章

  1. 【hash】A Horrible Poem

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

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

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

  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. P3538 [POI2012]OKR-A Horrible Poem

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

  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. 【BZOJ2795】[Poi2012]A Horrible Poem hash

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

随机推荐

  1. Spring MVC 使用介绍(十六)数据验证 (三)分组、自定义、跨参数、其他

    一.概述 除了依赖注入.方法参数,Bean Validation 1.1定义的功能还包括: 1.分组验证 2.自定义验证规则 3.类级别验证 4.跨参数验证 5.组合多个验证注解 6.其他 二.分组验 ...

  2. Flask 构建微电影视频网站(八)

    评论收藏及弹幕 实现电影评论添加及列表.数据查询实现统计播放量和评论量.jquery ajax实现收藏电影,flask结合redis消息队列实现电影弹幕,bug处理等功能. 电影评论-统计 class ...

  3. BZOJ 1815: [Shoi2006]color 有色图(Polya定理)

    题意 如果一张无向完全图(完全图就是任意两个不同的顶点之间有且仅有一条边相连)的每条边都被染成了一种颜色,我们就称这种图为有色图. 如果两张有色图有相同数量的顶点,而且经过某种顶点编号的重排,能够使得 ...

  4. Django视图

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  5. 关于 iOS 性能优化方面的面试题,

    这是我前面几天碰到的面试题: 如何对定位和分析项目中影响性能的地方?以及如何进行性能优化? 我的答案: 定位方法: instruments   在iOS上进行性能分析的时候,首先考虑借助instrum ...

  6. Redis-Cluster操作命令大全

    今天整理下redis-cluster操作命令 一.Cluster操作命令 CLUSTER INFO 打印集群的信息 CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相 ...

  7. Springboot集成FreeMarker

    Apache官网对FreeMarker的解释如下: Apache FreeMarker™是一个模板引擎 :一个基于模板和变化的数据来生成文本输出(HTML网页,电子邮件,配置文件,源代码,等等)的Ja ...

  8. 2018-2019-2 《Java程序设计》第8周学习总结

    20175319 2018-2019-2 <Java程序设计>第8周学习总结 教材学习内容总结 本周学习<Java程序设计>第十五章: 泛型: 泛型(Generics)的主要目 ...

  9. 深入理解JAVA中的代理模式

    前言 代理是什么 事故现场:我家的宠物今天生病了,而我又没有相关的医学知识,所以我只让我的宠物多喝热水吗? 结果显然是不行的,所以我需要去找宠物医生这些更专业的人来帮我的宠物治病. 这个时候,代理就出 ...

  10. Spring cloud gateway

    ==================================为什么需要API gateway?==================================企业后台微服务互联互通, 因为 ...