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. 【转】你知道C#中的Lambda表达式的演化过程吗?

    [转]你知道C#中的Lambda表达式的演化过程吗? 那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传 ...

  2. spring 学习 二 IOC/DI

    中文名称:控制反转 英文名称:( Inversion of Control ) 1 控制反转作用: 一般在编写java程序时,需要程序员自己创建对象的实例,例如 A a=new A();语句,就是程序 ...

  3. regular exception

    RegexBuddy :正则表达式编辑器. 正则表达式:通过特定的规则,选取特定的字符串. ^ 为匹配输入字符串的开始位置.$ 为匹配输入字符串的结束位置. \d匹配[0-9] \w匹配[A-Z a- ...

  4. Python之内置函数一

    一:绝对值,abs i = abs(-123) print(i) # 打印结果 123 二:判断真假,all,与any 对于all # 每个元素都为真,才是True # 假,0,None," ...

  5. [转]图解CSS的padding,margin,border属性(详细介绍及举例说明)

    图解CSS的padding,margin,border属性 W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层 ...

  6. 常用.bat

    休眠.bat rundll32 powrprof.dll,SetSuspendState 常用.bat start /d  "d:\Program Files (x86)\Tencent\T ...

  7. C++STL queue

    queue队列 先进先出 queue<int> q1; q1.push();//插入元素 q1.front();//求队头元素 q1.pop();//删除队头元素 q1.empty();/ ...

  8. Linux centos 连接网络

    1.在安装过程中不要选择网络适配器,其他正常执行 2.编辑 [root@zb ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 一般安装完软件,打开et ...

  9. 代码的二次重构(开篇:JDBC连接数据库)

    Java中使用JDBC连接数据库时,若是使用初级的代码,代码复用率非常低,连接过程简单来说分为以下几个步骤: 加载驱动包 准备好URL链接获取数据库连接(driver和url根据不同的数据库的不同而不 ...

  10. DDR中的命令

    (3) 列地址选择(CAS#): 选择器件内感兴趣的地址列 行地址选择(RAS#): 选择设备中感兴趣的地址行. (4)(precharge)预充电 DRAM读取具有破坏性,也就是说,在读操作中会破坏 ...