Maximum repetition substring
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


[2016-12-29 00:26]
从20点写(照代码抄)到现在....
不想写思路了,看论文吧,那么
整理一下调试过程的问题:
STL:
reverse(s+1,s+1+n) 第一个别写成s
ST表中:
1.预处理Log的话是N不是n..........silly
2.一定要写好了,i和j分清了别顺手写错,找好久还不知道问题出在哪
SA:
1.写了个调试函数test.....
2.通常不需要memset什么,注意重设m的范围吧
 
4个多小时不太值啊,不过也算是对后缀数组有了点感觉了吧,明天再写两道这样的题
现在什么错误都不要紧,省选时不要犯就好
 
[2016-12-29 12:36:21]
补一下做法:

重复次数最多的连续重复子串

论文:

先穷举长度 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表

 
[2017-02-06 ]
复习后缀数组又自己写了一遍.....
新问题:
1.求LCP别忘x++,因为是height
2.大于小于别写错了
3.反转之后别忘了转回来
#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表]的更多相关文章

  1. POJ3693 Maximum repetition substring —— 后缀数组 重复次数最多的连续重复子串

    题目链接:https://vjudge.net/problem/POJ-3693 Maximum repetition substring Time Limit: 1000MS   Memory Li ...

  2. POJ3693 Maximum repetition substring 后缀数组

    POJ - 3693 Maximum repetition substring 题意 输入一个串,求重复次数最多的连续重复字串,如果有次数相同的,则输出字典序最小的 Sample input ccab ...

  3. poj3693 Maximum repetition substring (后缀数组+rmq)

    Description The repetition number of a string is defined as the maximum number R such that the strin ...

  4. Maximum repetition substring 后缀数组

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7578   Acc ...

  5. POJ 3693 Maximum repetition substring ——后缀数组

    重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Thet ...

  6. 【Poj-3693】Maximum repetition substring 后缀数组 连续重复子串

    POJ - 3693 题意 SPOJ - REPEATS的进阶版,在这题的基础上输出字典序最小的重复字串. 思路 跟上题一样,先求出最长的重复次数,在求的过程中顺便纪录最多次数可能的长度. 因为sa数 ...

  7. poj 3693 Maximum repetition substring (后缀数组)

    其实是论文题.. 题意:求一个字符串中,能由单位串repeat得到的子串中,单位串重复次数最多的子串.若有多个重复次数相同的,输出字典序最小的那个. 解题思路:其实跟论文差不多,我看了很久没看懂,后来 ...

  8. POJ 3693 Maximum repetition substring (后缀数组+RMQ)

    题意:给定一个字符串,求其中一个由循环子串构成且循环次数最多的一个子串,有多个就输出最小字典序的. 析:枚举循环串的长度ll,然后如果它出现了两次,那么它一定会覆盖s[0],s[ll],s[ll*2] ...

  9. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

随机推荐

  1. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

  2. Mono为何能跨平台?聊聊CIL(MSIL)

    前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力 ...

  3. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题

    最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerP ...

  4. C#中那些[举手之劳]的性能优化

    隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒...... 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对大多数程序猿 ...

  5. PHP源码分析-变量

    1. 变量的三要素变量名称,变量类型,变量值 那么在PHP用户态下变量类型都有哪些,如下: // Zend/zend.h #define IS_NULL 0 #define IS_LONG 1 #de ...

  6. 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二)

    前言 文章 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 中,已经完成对 gulp 的安装,由于是window环境,文中特意提到了可以通过安装 gitbash 来代替 ...

  7. 23种设计模式--建造者模式-Builder Pattern

    一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建 ...

  8. 深入浅出JavaScript之原型链&继承

    Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...

  9. 个人网站对xss跨站脚本攻击(重点是富文本编辑器情况)和sql注入攻击的防范

    昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无限循环弹出框的脚本,估计 ...

  10. 重新认识了下Entity Framework

    什么是Entity Framework Entity Framework是一个对象关系映射O/RM框架. Entity Framework让开发者可以像操作领域对象(domain-specific o ...