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

题意:

找出原字符串中的重复次数最多的连续重复子串。

题解:

记这个连续重复子串为\(L\),我们可以发现,这个字符串一定会覆盖\(s[0],s[L],s[L*2]\).....这些点中相邻的两个(因为长度至少为\(2L\)嘛)。假设它覆盖的是\(s[L*i]\)和\(s[L*(i+1)]\),那么我们就往前和往后计算能匹配多远(往后匹配用到了后缀数组的height数组,往前匹配可以while到\(s[L*(i-1)]\),越过\(s[L*(i-1)]\)的情况和前面计算的重复了,可以不算)

记往前匹配和往后匹配的最长长度为k,则重复次数为\(k/L+1\)。

再求lcp的时候用st表优化一下即可

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
char s[N];
int n;
int fir[N],sec[N],rnk[N],t[N],sa[N],b[N];
double log2(double x){
return log(x)/log(2.0);
}
void msort(){
memset(t,0,sizeof t);
for(int i=1;i<=n;++i)t[sec[i]]++;
for(int i=1;i<N;++i)t[i]+=t[i-1];
for(int i=n;i;--i)b[t[sec[i]]--]=i;
memset(t,0,sizeof t);
for(int i=1;i<=n;++i)t[fir[b[i]]]++;
for(int i=1;i<N;++i)t[i]+=t[i-1];
for(int i=n;i;--i)sa[t[fir[b[i]]]--]=b[i];
}
int height[N];
void get_height(char *s){
int k=0;
for(int i=1;i<=n;++i){
if(rnk[i]==1){
height[i]=0;
continue;
}
if(k)--k;
int j=sa[rnk[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
height[i]=k;
}
}
int mn[N][20];
void get_height_st(){
for(int i=1;i<=n;++i)mn[i][0]=height[sa[i]];
int t=log2(n);
for(int i=1;i<=t;++i){
for(int j=1;j<=n;++j){
if(j+(1<<(i-1))>n)mn[j][i]=mn[j][i-1];
else mn[j][i]=min(mn[j][i-1],mn[j+(1<<(i-1))][i-1]);
}
}
}
int height_query(int l,int r){
l=rnk[l],r=rnk[r];
if(l>r)swap(l,r);l++;
int t=log2(r-l+1);
return min(mn[l][t],mn[r-(1<<t)+1][t]);
}
void get_sa(char *s){
for(int i=1;i<=n;++i)rnk[i]=s[i];
for(int k=1;k<=n;k*=2){
for(int i=1;i<=n;++i){
fir[i]=rnk[i];
if(i+k>n)sec[i]=0;
else sec[i]=rnk[i+k];
}
msort();
int num=1;rnk[sa[1]]=1;
for(int i=2;i<=n;++i){
if(fir[sa[i]]!=fir[sa[i-1]]||sec[sa[i]]!=sec[sa[i-1]])num++;
rnk[sa[i]]=num;
}
if(num==n)break;
}
}
int maxn,pos,len;
void find(){
maxn=1;
for(int i=1;i<=n/2;++i){
for(int j=1;j+i<=n;j+=i){
if(s[j]!=s[j+i])continue;
int k=height_query(j,j+i),now,r;
now=k/i+1,r=i-k%i;
int cnt=0,p=j;
for(int m=j-1;m>j-i&&s[m]==s[m+i]&&m;--m){
cnt++;
if(cnt==r)now++,p=m;
else p=rnk[p]>rnk[m]?m:p;
}
if(now>maxn)maxn=now,pos=p,len=i;
else if(now==maxn&&rnk[pos]>rnk[p])pos=p,len=i;
}
}
}
int main(){
int js=0;
while(1){
js++;
cin>>s+1;
if(s[1]=='#')break;
n=strlen(s+1);
get_sa(s);
get_height(s);
get_height_st();
find();
printf("Case %d: ",js);
for(int i=pos;i<=pos+len*maxn-1;++i){
putchar(s[i]);
}puts("");
}
}

Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)的更多相关文章

  1. Maximum repetition substring POJ - 3693(重复次数最多的连续重复子串)

    这题和SPOJ - REPEATS 一样  代码改一下就好了 这个题是求这个重复子串,还得保证字典序最小 巧妙运用sa 看这个 https://blog.csdn.net/queuelovestack ...

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

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

  3. SPOJ 687 Repeats(后缀数组+ST表)

    [题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...

  4. BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay

    BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...

  5. UVA10829 L-Gap Substrings(后缀数组+ST表)

    后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...

  6. POJ3693 Maximum repetition substring [后缀数组 ST表]

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

  7. 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分

    4310: 跳蚤 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 180  Solved: 83[Submit][Status][Discuss] De ...

  8. URAL 1297 Palindrome(后缀数组+ST表)

    [题目链接] http://acm.timus.ru/problem.aspx?num=1297 [题目大意] 求最长回文子串,并输出这个串. [题解] 我们将原串倒置得到一个新的串,加一个拼接符将新 ...

  9. UVA 11475 Extend to Palindrome(后缀数组+ST表)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...

随机推荐

  1. oracle的在没有安装服务端连接远处服务端的方法

    1.找到oracle的安装目录.如:C:\oracle\product\10.2.0\db_1\network\ADMIN 2.找到tnsnames.ora文件 3. 其中中文部分是需要修改的部分,除 ...

  2. 异常处理(异常解析器) 和 对于Properties类型的属性的配置

    在程序运行中,有可能因为用户的不当操作,发生异常.. 在springmvc中可以根据不同的异常配置不同的处理方式 1.例如出现 这个类型异常 org.springframework.web.multi ...

  3. jQuery Growl插件(消息提醒)

    ps:菜鸟教程 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <s ...

  4. ZOJ 3216 Compositions (矩阵快速幂)

    题意:求把 n 拆成几个大于等于 k 的数的和的方案数. 析:根据题目很容易写出递推式,f[i] = f[i-1] + f[i-k],什么意思呢,f[i-1] 表示是进行加 1 操作,那么可以给 n- ...

  5. c++中指针的指针和指针的引用的使用

    当指针作为函数的参数进行传递时,实际上本质上是安置传递,即将指针进行了一份拷贝,在函数的内部对这个指针的修改实际上就是对一个在函数内部的那个局部变量的修改.这点事和引用不同的,引用实际上是在参数传递时 ...

  6. tomcat部署项目访问不加项目名方法

    直接主题:tomcat部署项目访问不加项目名方法是打开tomcat的conf目录下server.xml文件 加入 <Context path="" docBase=" ...

  7. SQL常用增删改查

    转 http://www.cnblogs.com/daxueshan/p/6687521.html 1增 1.1[插入单行]insert [into] <表名> (列名) values ( ...

  8. word粘贴图片+的editor

    公司做的项目需要用到文本上传功能. Chrome+IE默认支持粘贴剪切板中的图片,但是我要粘贴的文章存在word里面,图片多达数十张,我总不能一张一张复制吧? 我希望打开文档doc直接复制粘贴到富文本 ...

  9. (转)memcached注意事项

    转自:http://www.kaifajie.cn/kaiyuan_qita/8656.html 1.   key值最大长度? memcached的key的最大长度是250个字符. 注意250是mem ...

  10. html5打开摄像头并用canvas模拟拍照 - 转

    <video id="video" width="640" height="480" autoplay></video&g ...