【BZOJ】2795: [Poi2012]A Horrible Poem
2015-11-22 13:56
363 查看
题意
一个长度为\(n(n \le 500000)\)的字符串\(s\),给\(q(q \le 2000000)\)个询问,每个询问给一个区间\([l, r]\),求这个区间内最短的循环节。分析
分析以下可以知道:假设循环节长度为\(len\),则\(s[l, r-len]=s[l+len, r]\)。
\(len|(r-l+1)\)
如果\(len\)是循环节,则\(len * p\)也是循环节\((len * p|(r-l+1))\)
题解
首先判两个串是否相等用hash即可。根据\(1, 2\)我们很容易得到\(O(qn^{0.5})\)的做法。
可是由于性质\(3\)的存在,我们先分解\((r-l+1)\)的质因数,然后依次考虑删去质因数即可。
复杂度\(O(qlogn)\)
#include <bits/stdc++.h> using namespace std; inline int getint() { int x=0, c=getchar(); for(; c<48||c>57; c=getchar()); for(; c>47&&c<58; x=x*10+c-48, c=getchar()); return x; } const unsigned int N=500005, mo=1e9+7; int p , cnt, m , bg ; unsigned int a , po ; void init(int n) { for(int i=2; i<=n; ++i) { if(!bg[i]) { bg[i]=i; p[cnt++]=i; } for(int j=0, t; j<cnt; ++j) { t=p[j]*i; if(t>n) { break; } bg[t]=p[j]; if(i%p[j]==0) { break; } } } } inline bool check(int a, int b, int c, int d) { return m[b]-m[a-1]*po[b-a+1]==m[d]-m[c-1]*po[d-c+1]; } int main() { int n=getint(); init(n); po[0]=1; for(int i=1; i<=n; ++i) { m[i]=m[i-1]*mo+getchar(); po[i]=po[i-1]*mo; } int q=getint(); for(; q--; ) { int l=getint(), r=getint(), len=r-l+1; for(int x=len; x>1; ) { int y=bg[x]; for(; len%y==0 && check(l, r-len/y, l+len/y, r); len/=y); for(; x%y==0; x/=y); } printf("%d\n", len); } return 0; }
相关文章推荐
- 名校家教-webview 设置
- 执行protoc命令时提示找不到共享库的错误【要把新共享库目录加入到共享库配置文件/etc/ld.so.conf】
- SQL Server 中 Index Allocation Map(IAM)介绍 01
- 在面试机器学习、大数据岗位时遇到的各种问题
- java对象序列化
- javascript--自动填充 与 多选级联
- 【BZOJ】2729: [HNOI2012]排队
- 面向对象包的设计原则ADP/SDP/SAP与包的设计度量工具jDepend
- 分页的另一种实现-不用额外请求
- Android开发手记(8) ProgressDialog的使用
- IOS UI 动画用到的一些 效果
- 日经春秋 20151122
- ubuntu下启动、关闭tomcat,查看tomcat运行日志
- 【BZOJ】2697: 特技飞行
- ElasticSearch里JAVA环境丢失的问题
- gdb 调试的信息输出到文件
- PHP - 类库
- android 适配器优化,viewholder的使用
- 【BZOJ】2675: Bomb
- C++IO流简介