Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5946   Accepted: 1799

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
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
#include <iomanip>
#define INF 99999999
typedef long long LL;
using namespace std; const int MAX=100000+10;
int *rank,r[MAX],sa[MAX],height[MAX],L[MAX];
int wa[MAX],wb[MAX],wm[MAX],f[MAX][32];
char s[MAX]; bool cmp(int *r,int a,int b,int l){
return r[a] == r[b] && r[a+l] == r[b+l];
} void makesa(int *r,int *sa,int n,int m){
int *x=wa,*y=wb,*t;
for(int i=0;i<m;++i)wm[i]=0;
for(int i=0;i<n;++i)wm[x[i]=r[i]]++;
for(int i=1;i<m;++i)wm[i]+=wm[i-1];
for(int i=n-1;i>=0;--i)sa[--wm[x[i]]]=i;
for(int i=0,j=1,p=0;p<n;j=j*2,m=p){//j表示合并的子串长度
for(p=0,i=n-j;i<n;++i)y[p++]=i;//对第二关键字超出数组范围的子串排序
for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;//对剩下子串根据第二关键字排序
for(i=0;i<m;++i)wm[i]=0;
for(i=0;i<n;++i)wm[x[y[i]]]++;
for(i=1;i<m;++i)wm[i]+=wm[i-1];
for(i=n-1;i>=0;--i)sa[--wm[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;++i){//求新的x,相当于rank,但是相同的子串要排名相同
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;//判断子串suffix(sa[i])与suffix(sa[i-1])是否相同并且确定排名
}
}
rank=x;
} /*在计算好height[rank[i]]后,对于height[rank[i+1]],如果sa[rank[i]-1]的首字母和sa[rank[i]]首字母相同
则rank[i+1]肯定在rank[sa[rank[i]-1]+1]后面,根据排名为a,b的子串的最长公共前缀为[a,b]中最小的
所以i+1和sa[rank[i+1]-1]的公共前缀>=height[rank[i]]-1即>=k-1;
如果sa[rank[i]-1]的首字母和sa[rank[i]]首字母不相同,则上一次的k就是0,所以无影响
*/
void calheight(int *r,int *sa,int n){
for(int i=0,j=0,k=0;i<n;height[rank[i++]]=k){
for(k?--k:0,j=sa[rank[i]-1];r[i+k] == r[j+k];++k);
}
} void InitRMQ(int n){
for(int i=1;i<=n;++i)f[i][0]=height[i];//初始化从i开始区间长度为2^0的最值
int l=log(n*1.0)/log(2.0);//2*l<=n
for(int j=1;j<=l;++j){
for(int i=1;i+(1<<j)-1<=n;++i){//i+2^j-1<=n
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);//i+2^j-1 - (i+2^(j-1))+1=2^(j-1)
}
}
} int LCP(int i,int j){//求rank[i]与rank[i]+1,ran[i]+1与rank[i]+2...的最长公共前缀中的最值,即height[rank[i]+1]~height[rank[j]]的最值
i=rank[i],j=rank[j];
if(i>j)swap(i,j);
++i;
int l=log(j-i+1.0)/log(2.0);//2^l<=j-i+1
return min(f[i][l],f[j-(1<<l)+1][l]);
} int main(){
int Case=0;
while(scanf("%s",s),s[0] != '#'){
int n=0;
for(n=0;s[n] != '\0';++n)r[n]=s[n];
r[n]=0;
makesa(r,sa,n+1,256);
calheight(r,sa,n);
InitRMQ(n);
int sum=0,size=0,x=sa[1],y=sa[1]+1;
for(int j=1;j<=n;++j){//对于长度为j的循环节,sum记录循环次数
for(int i=0;i+j<n;i+=j){
if(s[i] == s[i+j]){
int len=LCP(i,i+j);//向后匹配
int num=len/j;
int k=i-(j-len%j);
if(k>=0 && len%j && LCP(k,k+j)>=len)++num;//向前匹配
if(num == sum)L[++size]=j;//L记录得到最多循环次数的可能的子串长度
else if(num > sum)sum=num,L[size=0]=j;
}
}
}
for(int i=1;i<=n && sum;++i){//求哪个子串可以循环sum次
for(int j=0;j<=size;++j){
if(sa[i]+L[j]>=n)continue;
int len=LCP(sa[i],sa[i]+L[j]);
if(len/L[j] == sum){x=sa[i],y=sa[i]+(sum+1)*L[j],sum=0;break;}
}
}
printf("Case %d: ",++Case);
for(int i=x;i<y;++i)printf("%c",s[i]);
printf("\n");
}
return 0;
}

poj3693之后缀数组的更多相关文章

  1. poj3693(后缀数组)

    poj3693 题意 给出一个串,求重复次数最多的连续重复子串,输出字典序最小的. 分析 论文 例8(P21). Sparse-Table算法预处理出任意两个后缀串的LCP. code #includ ...

  2. POJ3693(SummerTrainingDay10-J 后缀数组)

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10241   Ac ...

  3. 【poj3693】Maximum repetition substring(后缀数组+RMQ)

    题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...

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

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

  5. POJ3693 Maximum repetition substring 后缀数组

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

  6. 关于后缀数组的倍增算法和height数组

    自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...

  7. 【UVA10829】 L-Gap Substrings (后缀数组)

    Description If a string is in the form UVU, where U is not empty, and V has exactly L characters, we ...

  8. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  9. 【距离GDOI:131天】 后缀数组完毕

    用了近两周的时间,终于把罗神那篇后缀数组应用看完了,题目也写了一遍,T了无数次...详见前几篇博文... 后缀数组很重要的是那个height数组,可以用来做各种奇奇怪怪的东西...常用方法去是去二分, ...

随机推荐

  1. png图片压缩优化

    1.2 软件环境 软件名称:Opting下载地址: http://optipng.sourceforge.net/ 安装版本:0.7.5安装位置:/apps/svr/opting 安装可能遇到的问题: ...

  2. zzbank oneOpencloud Env linuxaix6.1 interactiveMaintain(nfs,aix genintall基于系统iso光盘,aix6.1 puppet-Agent,Cent6.4 puppetServer,agent time no syn case Er)

    1,puppet--server,Client,Agent time no syn case eror puppet agent --server frontend -terr: Could not ...

  3. ios中的银联支付

    场景 随着移动互联网的迅猛发展,移动互联已经深深地融入我们的生活.其中,支付方式也是我们生活中经常遇到的情况.所以,在我们的应用中加入支付功能是多么的重要.现在主流的支付接口,一是支付宝类的,一是银联 ...

  4. Ubuntu下远程访问MySQL数据库

    MySQL远程访问的命令 格式: mysql -h主机地址 -u用户名 -p用户密码 jack@jack:~$ mysql -h192.168.5.154 -usaledata -pEnter pas ...

  5. 百度 LBS 开放平台,开发人员众測计划正式启动

    Hi各位亲爱滴开发人员:   你是否以前-- 期望第一时间率先接触到百度LBS开放平台的最新功能? 期望被邀请作为最最尊贵的首批试用志愿者感受志愿者的特权? 期望自己的意见被产品经理採纳.优化功能.从 ...

  6. spring+hibernate基础

    把数据库的配置信息写在一个文件中 jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\:3306/ ...

  7. java内存映射文件

    内存映射文件能够让我们创建和修改大文件(大到内存无法读入得文件),对于内存映射文件,我们可以认为是文件已经全部被读入到内存当中,然后当成一个大的数字来访问,简化修改文件的代码. 1.directBuf ...

  8. 关于已经安装python为何还要安装python-dev

    linux发行版通常会把类库的头文件和相关的pkg-config分拆成一个单独的xxx-dev(el)包. 以python为例, 以下情况你是需要python-dev的 你需要自己安装一个源外的pyt ...

  9. pprint模块解析

    pprint模块提供了打印任意python数据结构的方法,如果这个数据结构不是python的基本类型,则可能无法打印结果.         pprint模块定义了一个类:         pprint ...

  10. css中z-index属性(标签层叠次序)

    定义和用法 z-index 属性设置元素的堆叠顺序.拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面. 注释:元素可拥有负的 z-index 属性值. 注释:Z-index 仅能在定位元素上奏 ...