POJ3693 Maximum repetition substring [后缀数组 ST表]
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 9458 | Accepted: 2915 |
Description
The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.
Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.
Input
The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.
The last test case is followed by a line containing a '#'.
Output
For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.
Sample Input
ccabababc
daabbccaa
#
Sample Output
Case 1: ababab
Case 2: aa
Source
重复次数最多的连续重复子串
论文:
先穷举长度 L,然后求长度为 L 的子串最多能连续出现几次。首先连续出现1 次是肯定可以的,所以这里只考虑至少 2 次的情况。假设在原字符串中连续出 现 2 次,记这个子字符串为 S,那么 S 肯定包括了字符 r[0], r[L], r[L*2], r[L*3], ......中的某相邻的两个。所以只须看字符 r[L*i]和 r[L*(i+1)]往前和 往后各能匹配到多远,记这个总长度为 K,那么这里连续出现了 K/L+1 次。最后 看最大值是多少。
穷举长度 L 的时间是 n,每次计算的时间是 n/L。所以整个做法的时间复杂度是 O(n/1+n/2+n/3+......+n/n)=O(nlogn)。
我们不知道它的长度,所以只能枚举长度
对于长度L,他的连续重复子串有的话一定覆盖掉s[1+L*i]中的相邻两个,我们把这样的位置成为“关键点”
所以对于每相邻两个位置(关键点)s[1+L*i]和s[1+L*(i+1)],求出他们往左和往右能匹配多远l和r(我的r是包括了这个关键点),然后在这一段内连续重复的次数step=(l+r)/L+1
(因为...自己想想吧,比如对于左端点,移动之后还是相同,还是两个左端点隔了L的距离)
一个重要的问题是字典序最小
对于靠左关键点i,向左能延伸l的话,[i-l,i-l+(l+r)%L]这个区间内开始大小重复次数不变((l+r)%L就是说这一个长度是空余的可以随便左右放),所以这一段求rnk最小值作为开始,同样对rnk处理ST表
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+,INF=1e9;
int n,m,c[N],t1[N],t2[N];
char s[N]; int mn[N][],Log[N],Pow[];
void iniST(){
Pow[]=;for(int i=;i<;i++) Pow[i]=Pow[i-]<<;
Log[]=-;for(int i=;i<N;i++) Log[i]=Log[i>>]+;
}
void getST(int mn[N][],int a[N]){
for(int i=;i<=n;i++) mn[i][]=a[i];
for(int j=;j<=Log[n];j++)
for(int i=;i+Pow[j]-<=n;i++)
mn[i][j]=min(mn[i][j-],mn[i+Pow[j-]][j-]);
}
int RMQ(int x,int y){
if(x>y) swap(x,y);
int _=Log[y-x+];
return min(mn[x][_],mn[y-Pow[_]+][_]);
}
struct SA{
int sa[N],rnk[N],height[N];
inline bool cmp(int *r,int a,int b,int j){
return a+j<=n&&b+j<=n&&r[a]==r[b]&&r[a+j]==r[b+j];
}
void getSA(char s[]){
m=;
int *r=t1,*k=t2;
for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[r[i]=s[i]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[i]]--]=i; for(int j=;j<=n;j<<=){
int p=;
for(int i=n-j+;i<=n;i++) k[++p]=i;
for(int i=;i<=n;i++) if(sa[i]>j) k[++p]=sa[i]-j; for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[r[k[i]]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[k[i]]]--]=k[i]; swap(r,k);p=;r[sa[]]=++p;
for(int i=;i<=n;i++) r[sa[i]]=cmp(k,sa[i],sa[i-],j)?p:++p;
if(p>=n) break;m=p;
}
}
void getHeight(char s[]){
for(int i=;i<=n;i++) rnk[sa[i]]=i;
int k=;
for(int i=;i<=n;i++){
if(k) k--;
if(rnk[i]==) continue;
int j=sa[rnk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
height[rnk[i]]=k;
}
}
int mn[N][];
void ini(char s[]){getSA(s);getHeight(s);getST(mn,height);}
int lcp(int x,int y){
x=rnk[x];y=rnk[y];
if(x>y) swap(x,y);x++;//!!!
int _=Log[y-x+];
return min(mn[x][_],mn[y-Pow[_]+][_]);
}
}a,b; int cas=;
void solve(){
int lexi=INF,mx=,al=,ar=;
for(int L=;L<=n;L++){
for(int i=;i+L<=n;i+=L){
int l=b.lcp(n-i+,n-(i+L)+),r=a.lcp(i,i+L);
int step=(l+r)/L+;
if(step>mx){
mx=step;
int _=RMQ(i-l,i-l+(l+r)%L);
lexi=_;
al=a.sa[_],ar=al+L*step-;
}else if(step==mx){
int _=RMQ(i-l,i-l+(l+r)%L);
if(_<lexi) lexi=_,al=a.sa[_],ar=al+L*step-;
}
}
} printf("Case %d: ",++cas);
reverse(s+,s++n);
for(int i=al;i<=ar;i++) putchar(s[i]);
puts("");
}
int main(){
freopen("in","r",stdin);
iniST();
while(scanf("%s",s+)!=EOF){
if(s[]=='#') break;
n=strlen(s+);
a.ini(s);
//for(int i=1;i<=n;i++) printf("a %d %d %d\n",i,a.rnk[i],a.height[i]);
reverse(s+,s++n);
b.ini(s);
getST(mn,a.rnk);
solve();
}
}
2.26.2017
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+,INF=1e9;
int n,m,c[N],t1[N],t2[N];
char s[N];
inline bool cmp(int *r,int a,int b,int j){
return a+j<=n&&b+j<=n&&r[a]==r[b]&&r[a+j]==r[b+j];
}
int Log[N],Pow[],mn[N][]; void iniST(){
Pow[]=;for(int i=;i<;i++)Pow[i]=Pow[i-]<<;
Log[]=-;for(int i=;i<=;i++)Log[i]=Log[i/]+;
}
void getST(int mn[N][],int a[]){
for(int i=;i<=n;i++) mn[i][]=a[i];
for(int j=;j<=Log[n];j++)
for(int i=;i+Pow[j]-<=n;i++)
mn[i][j]=min(mn[i][j-],mn[i+Pow[j-]][j-]);
} inline int rmq(int x,int y){
int t=Log[y-x+];
return min(mn[x][t],mn[y-Pow[t]+][t]);
} struct SA{
int sa[N],rnk[N],height[N],mn[N][]; void getHeight(){
int k=;
for(int i=;i<=n;i++) rnk[sa[i]]=i;
for(int i=;i<=n;i++){
if(k) k--;
if(rnk[i]==) continue;
int j=sa[rnk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
height[rnk[i]]=k;
}
}
void getSA(){
int *r=t1,*k=t2;
for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[r[i]=s[i]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[i]]--]=i; for(int j=;j<=n;j<<=){
int p=;
for(int i=n-j+;i<=n;i++) k[++p]=i;
for(int i=;i<=n;i++) if(sa[i]>j) k[++p]=sa[i]-j; for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[r[k[i]]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[k[i]]]--]=k[i]; swap(r,k);p=;r[sa[]]=++p;
for(int i=;i<=n;i++) r[sa[i]]=cmp(k,sa[i],sa[i-],j)?p:++p;
if(p>=n) break;m=p;
}
} int lcp(int x,int y){
x=rnk[x];y=rnk[y];
if(x>y) swap(x,y);x++;
int t=Log[y-x+];
return min(mn[x][t],mn[y-Pow[t]+][t]);
} void ini(){
m=;
getSA();getHeight();getST(mn,height);
}
void test(){
for(int i=;i<=n;i++) printf("%c ",s[i]);puts("");
for(int i=;i<=n;i++) printf("%d ",rnk[i]);puts("");
for(int i=;i<=n;i++) printf("%d ",sa[i]);puts("");
for(int i=;i<=n;i++) printf("%d ",height[i]);puts("");
puts("");
}
}a,b;
int mx,ans,ansl,ansr;
void solve(int L){//printf("sol %d\n",L);
for(int i=;i+L<=n;i+=L)
if(s[i]==s[i+L]){
int r=a.lcp(i,i+L),l=b.lcp(n-i+,n-i-L+);
int step=(l+r)/L+;//printf("hi %d %d lr %d %d step %d\n",i,L,l,r,step);
if(step>mx) mx=step,ans=INF;//,printf("mx %d\n",mx);
if(step==mx){
int t=rmq(i-l,i-l+(l+r)%L);//printf("t %d\n",t);
if(t<ans){
ans=t;
ansl=a.sa[t],ansr=ansl+mx*L-;
}
}
}
} int main(){
int cas=;
iniST();
while(scanf("%s",s+)!=EOF){
if(s[]=='#') break;
n=strlen(s+);
a.ini();//a.test();
reverse(s+,s++n);
b.ini();//b.test(); getST(mn,a.rnk);
reverse(s+,s++n);
mx=;ans=INF;ansl=ansr=;
for(int i=;i<=n;i++)
if(a.rnk[i]<ans) ans=a.rnk[i],ansl=ansr=i;
for(int L=;L<=n;L++) solve(L); printf("Case %d: ",++cas);
for(int i=ansl;i<=ansr;i++) putchar(s[i]);
puts(""); }
}
POJ3693 Maximum repetition substring [后缀数组 ST表]的更多相关文章
- POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串
题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS Memory Li ...
- POJ3693 Maximum repetition substring 后缀数组
POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...
- poj3693 Maximum repetition substring (后缀数组+rmq)
Description The repetition number of a string is defined as the maximum number R such that the strin ...
- Maximum repetition substring 后缀数组
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7578 Acc ...
- POJ 3693 Maximum repetition substring ——后缀数组
重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...
- 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串
POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...
- poj 3693 Maximum repetition substring (后缀数组)
其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...
- POJ 3693 Maximum repetition substring (后缀数组+RMQ)
题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...
- POJ 3693 Maximum repetition substring(后缀数组+ST表)
[题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...
随机推荐
- 关于几个主流语音SDK的接入问题
这两周都在忙着游戏上线还有接入游戏语音,两周分别接了腾讯语音和百度语音!!! 关于腾讯语音的一些问题 由于发现腾讯语音的在录完音频后的数据是编过码的所以出现了一些问题: *不能解码(腾讯方不提供解码算 ...
- “四核”驱动的“三维”导航 -- 淘宝新UI(需求分析篇)
前言 孔子说:"软件是对客观世界的抽象". 首先声明,这里的"三维导航"和地图没一毛钱关系,"四核驱动"和硬件也没关系,而是为了复杂的应用而 ...
- web前端基础知识
#HTML 什么是HTML,和他ML... 网页可以比作一个装修好了的,可以娶媳妇的房子. 房子分为:毛坯房,精装修 毛坯房的修建: 砖,瓦,水泥,石头,石子.... 精 ...
- ExtJS 4.2 介绍
本篇介绍ExtJS相关知识,是以ExtJS4.2.1版本为基础进行说明,包括:ExtJS的特点.MVC模式.4.2.1GPL版本资源的下载和说明以及4种主题的演示. 目录 1. 介绍 1.1 说明 1 ...
- video.js
1.github地址 2.常用API: class : video-js: video-js应用视频所需的风格.js功能,比如全屏和字幕. vjs-default-skin: vjs-default- ...
- [版本控制之道] Git 常用的命令总结(欢迎收藏备用)
坚持每天学习,坚持每天复习,技术永远学不完,自己永远要前进 总结日常开发生产中常用的Git版本控制命令 ------------------------------main-------------- ...
- Xamarin与Visual stuido2015离线安装包分享
最近看见大伙留言才知道国内安装Xamarin开发原来这么艰辛啊! 第一:网速不快 第二:Android SDK下载受限 等等... 鉴于这些原因,特写下这篇文章以及分享打包好的离线包以帮助大家尽快体验 ...
- WebApi返回Json格式字符串
WebApi返回json格式字符串, 在网上能找到好几种方法, 其中有三种普遍的方法, 但是感觉都不怎么好. 先贴一下, 网上给的常用方法吧. 方法一:(改配置法) 找到Global.asax文件,在 ...
- __Block与__Weak区别
一.__block理解: Blocks可以访问局部变量,但是不能修改, 声明block的时候实际上是把当时的临时变量又复制了一份, 在block里即使修改了这些复制的变量,也不影响外面的原始变量.即所 ...
- https 安全验证问题
最近为了满足苹果的 https 要求, 经过努力终于写出了方法 验证 SSL 证书是否满足 ATS 要求 nscurl --ats-diagnostics --verbose https://你的域名 ...