# 10038. 「一本通 2.1 练习 4」A Horrible Poem

【题目描述】

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

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

【算法】

-首先对于长度为 $len$ 的子串,循环节长度为 $x$ 的充要条件:$[1,len-x]$串的哈希值等于 $[x+1,len]$ 串的哈希值。

-一开始暴力枚举最短循环节长度(n的约数),然后T了一半。

有两种方法进行优化:

1、循环节个数必然是子串各个字母个数和子串长度的公约数,可以枚举循环节个数此时bzoj就能过了,但是loj还是会T。(93分) $O(q\sqrt{n})$

2、正解:假设最短循环节长度为len则原串长度显然为len*k。若只考虑k,并且将k的质因数依次分解,每次试除k,则得到的$k^。$和len的乘积仍是循环节,利用这个性质。依次用质因数 $i$ 试除n,若除去后仍是循环节,说明i属于k,将其除去,结果就留下了len。

【代码1】

  1. #include <bits/stdc++.h>
  2. #define P 131
  3. #define ULL unsigned long long
  4. using namespace std;
  5. int n,q,a,b,len;
  6. int rec[500010][26];
  7. ULL h[500010],p[500010];
  8. char s[500010];
  9. inline int read() {
  10. int x=0,f=1; char c=getchar();
  11. while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
  12. while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
  13. return x*f;
  14. }
  15. void parse() {
  16. p[0]=1;
  17. for(int i=1;i<=n;i++) p[i]=p[i-1]*P,h[i]=h[i-1]*P+(ULL)s[i];
  18. for(int i=1;i<=n;i++)
  19. for(int j=1;j<=26;j++)
  20. rec[i][j]=rec[i-1][j]+(s[i]-'a'+1==j);
  21. }
  22. int gcd(int x,int y) {
  23. return y?gcd(y,x%y):x;
  24. }
  25. bool valid(int l) {
  26. return h[b]-h[a+l-1]*p[len-l]==h[a+(len/l-1)*l-1]-h[a-1]*p[len-l];
  27. }
  28. int main() {
  29. n=read();
  30. gets(s+1);
  31. q=read();
  32. parse();
  33. while(q--) {
  34. a=read(),b=read();
  35. len=b-a+1;
  36. int num=len,ans=0;
  37. for(int i=1;i<=26;i++) num=gcd(num,rec[b][i]-rec[a-1][i]);
  38. for(int i=1;i*i<=num;i++) {
  39. if(num%i==0) {
  40. if(valid(len/(num/i))) { ans=max(ans,num/i); break; }
  41. if(valid(len/i)) ans=max(ans,i);
  42. }
  43. }
  44. printf("%d\n",len/ans);
  45. }
  46. return 0;
  47. }

【ac代码】

  1. #include <bits/stdc++.h>
  2. #define N 500010
  3. #define P 131
  4. #define ULL unsigned long long
  5. using namespace std;
  6. int n,q,len,tot;
  7. ULL h[N],p[N];
  8. int prime[N],minp[N];
  9. char s[N];
  10. inline int read() {
  11. int x=0,f=1; char c=getchar();
  12. while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
  13. while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
  14. return x*f;
  15. }
  16. void parse() {
  17. for(int i=2;i<=n;i++) {
  18. if(!minp[i]) {
  19. prime[++tot]=i;
  20. minp[i]=i;
  21. }
  22. for(int j=1;j<=tot;j++) {
  23. if(prime[j]>minp[i]||prime[j]*i>n) break;
  24. minp[prime[j]*i]=prime[j];
  25. }
  26. }
  27. p[0]=1;
  28. for(int i=1;i<=n;i++)
  29. h[i]=h[i-1]*P+(ULL)s[i],p[i]=p[i-1]*P;
  30. }
  31. bool valid(int a,int b,int l) {
  32. return h[b]-h[a+l-1]*p[len-l]==h[a+(len/l-1)*l-1]-h[a-1]*p[len-l];
  33. }
  34. int main() {
  35. n=read();
  36. gets(s+1);
  37. q=read();
  38. parse();
  39. while(q--) {
  40. int a,b,ans,tmp;
  41. a=read(),b=read();
  42. len=tmp=ans=b-a+1;
  43. while(tmp!=1) {
  44. int t=minp[tmp];
  45. while(tmp%t==0&&valid(a,b,ans/minp[tmp])) tmp/=t,ans/=t;
  46. while(tmp%t==0) tmp/=t;
  47. }
  48. printf("%d\n",ans);
  49. }
  50. return 0;
  51. }

A Horrible Poem (字符串hash+数论)的更多相关文章

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

  2. 【hash】A Horrible Poem

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

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

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

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

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

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

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

  6. 2795: [Poi2012]A Horrible Poem

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

  7. [BZOJ2795][Poi2012]A Horrible Poem

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

  8. #10038.A Horrible Poem

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

  9. P3538 [POI2012]OKR-A Horrible Poem

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

随机推荐

  1. elasticsearch 单实例安装启动

    elasticsearch 初次启动 下载 elasticsearch-6.3.2.tar.gz 创建目录 /usr/local/elasticsearch/ 解压 tar -zxf elastics ...

  2. DL反向传播理解

    作者:寒小阳 时间:2015年12月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/50321873 声明:版权所有,转载请联系作者并注明 ...

  3. JvmOverloads kotlin(14)(转)

    在Kotlin中@JvmOverloads注解的作用就是:在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法.可能还是云里雾里,直接上代码,代码解释一切:如果 ...

  4. 【React自制全家桶】三、React使用ref操作DOM与setState遇到的问题

    在React中同时使用ref操作DOM与setState常常会遇到 比如操作的DOM是setState更新之前的DOM内容,与想要的操作不一致.导致这样的原因是setState函数是异步函数. 就是当 ...

  5. phpStudy本地搭建wordpress教程

    一.启用phpStudy环境包 phpStudy简单易用,一键启动配置本地环境; 二.wordpress博客程序 登陆wordpress官网下载最新程序,解压后提取wordpress目录下全部文件到p ...

  6. kubernetes系列:(三)、helm的安装和使用

    一.helm简介 kubernetes : 解决了容器维护的难题,通过yaml编写,比如deployment,job,statefulset.configmap等等,通过控制循环,让容器镜像便于管理, ...

  7. gimp怎么移动选取中的图像并创建图层

    gimp怎么移动选取中的图像并创建图层 https://jingyan.baidu.com/article/414eccf6bf4d6e6b431f0a3b.html 听语音 原创 | 浏览:1148 ...

  8. 【MyEclipse优化】-----如何合理设置MyEclipse中的validation选项

    打开eclipse,点击[window]菜单,选择[preferences]选项. 在左侧点击[validation]选项,在右侧可以看到eclipse进行的自动检查都有哪些内容. 将Manual(手 ...

  9. php使用装饰模式无侵入式加缓存

    <?php namespace App\Services; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\ ...

  10. <转>经典测试用例:电梯、杯子、桌子、洗衣机

    1.测试项目:电梯 需求测试:查看电梯使用说明书.安全说明书等 界面测试:查看电梯外观 功能测试:测试电梯能否实现正常的上升和下降功能.电梯的按钮是否都可以用: 电梯门的打开,关闭是否正常:报警装置是 ...