BZOJ2795: [Poi2012]A Horrible Poem
2016-06-22 18:52
357 查看
题目大意:给一个字符串和多个询问,每次询问区间内最短循环节长度
假设我们找到一个长度,然后变成判定问题
如何判定呢?假如当前枚举长度为x,字符串总长为L,只需判断两点:
1.x是不是L的约数
2.这个字符串移除前x个字符和移除后x个字符之后的字符串是否完全匹配
因为满足条件2时,可以证明gcd(x,L)一定是一个合法答案,又因为x是L的约数,所以x就是一个合法答案
怎么判断字符串是否相等呢?可以hash,hash虚了可以用双hash或者后缀数组+RMQ
怎么枚举长度呢?直接找26个字母出现次数和总长度的公约数,然后根号L的时间复杂度就可以出解啦!
假设我们找到一个长度,然后变成判定问题
如何判定呢?假如当前枚举长度为x,字符串总长为L,只需判断两点:
1.x是不是L的约数
2.这个字符串移除前x个字符和移除后x个字符之后的字符串是否完全匹配
因为满足条件2时,可以证明gcd(x,L)一定是一个合法答案,又因为x是L的约数,所以x就是一个合法答案
怎么判断字符串是否相等呢?可以hash,hash虚了可以用双hash或者后缀数组+RMQ
怎么枚举长度呢?直接找26个字母出现次数和总长度的公约数,然后根号L的时间复杂度就可以出解啦!
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 500010 using namespace std; char s ; int pre [27]; int gcd(int a,int b) { if(!a) return b; return gcd(b%a,a); } long long h ,bas=233,mod=1e9+7,cf ; int geth(int x,int l) { return ((h[x+l-1]-h[x-1]*cf[l])%mod+mod)%mod; } bool judge(int x,int y,int l) { int L=y-x+1; if(l==y-x+1) return true; if(geth(x,L-l)==geth(x+l,L-l)) return true; return false; } int main() { int n; scanf("%d",&n); scanf("%s",s+1); int q,x,y,i,j; scanf("%d",&q); int maxl; cf[0]=1; for(i=1;i<=n;i++) { cf[i]=cf[i-1]*bas%mod; h[i]=(h[i-1]*bas+s[i]-96)%mod; for(j=1;j<=26;j++) pre[i][j]=pre[i-1][j]; pre[i][s[i]-96]++; } while(q--) { scanf("%d%d",&x,&y); maxl=y-x+1; for(i=1;i<=26;i++) maxl=gcd(maxl,pre[y][i]-pre[x-1][i]); int ans=0,L=y-x+1; for(i=1;i<=sqrt(maxl);i++) if(maxl%i==0) { if(judge(x,y,L/(maxl/i))) {ans=L/(maxl/i);break;} else if(judge(x,y,L/i)) ans=L/i; } printf("%d\n",ans); } }
相关文章推荐
- NYOJ 三个水杯 题解
- linux gzip gunzip
- java 正则表达式
- 聊聊拥堵费
- 京东“竖亥小车”秒测商品尺寸重量
- BZOJ3551: [ONTAK2010]Peaks加强版
- Android ViewGroup事件分发机制
- Ionic实战九:ionic视频播放
- python mysql
- 开发RESTful web Service
- 51CTO学院三周年-我的rhec7认证之路
- 一:Java 并发和多线程的介绍
- 职工系统150206204
- Android View 事件分发机制 源码解析
- java端RESTful web services的几种实现方式
- 基于RESTful API 怎么设计用户权限控制?
- 分布式存储之MogileFS分布式文件系统简单应用
- virtualbox安装增强功能时【未能加载虚拟光盘】
- redis初步接触
- Teechart在VC++中使用的碎碎念